POJ - 3069
题目
一个游戏:在一条直线上有N个糖果。第i个糖果的位置是X[i]。从这N个糖果中选择若干个,把他们标记起来。对于每一个糖果,在和它本身相距为R的区域内必须要有标记的糖果(本身带有标记的糖果,就可以认为和它相距为0的地方有一个糖果被标记)。在满足这个条件的情况,最后如果有a个糖果被标记,编写程序使a最小化。
输入
输入的测试文件将包含多个样例。 每个测试样例第一行有两个数据,整数R(其中0≤R≤1000)和整数N(其中1≤N≤1000)。 下一行包含N个整数,指示每个糖果的位置X[1],…,X[N](其中0≤X[i]≤1000)。当R == N== -1时,输入结束。
输出
对于每组输入数据,输出一个数,代表a的最小值。
样例
输入样例1
0 3
10 20 20
10 7
70 30 1 7 15 20 50
-1 -1
输出样例1
2
4
分析
入门级贪心问题,思路其实不难,最开始想的和书上差不多只是方向反了,直接从point+r开始向回找,这个思路其实也行,但代码实现有问题
本题既然是统计标记多少个点,就从第一个点开始找,找到要标记的第一个点之后再在这个点往后最大r的位置之内标记新一个点再对这个点往后找r,如此往复……
代码实现的问题在于习惯了用for之后总是不会用while...这个真的有点伤
还有测试数据会出现有多个点相同的情况,最开始以为需要把相同的点去掉只留一个点(淦);对此我的方法是sort之后套两层循环,找到之后跳过这个点,把后面的用第二层for接上来,然后n自减一次。在网上看到了另一种代码实现:基于打表实现,直接在输入的时候解决:
int vis[2000];
memset(vis, 0, sizeof(vis));//标记这些点为未访问状态
for (int i=0; i<n; i++){
int num;
scanf("%d", &num);//读入当前数
if (vis[num] == 0){//如果未被访问过
vis[num]++; //先标记为已访问过
a[j++] = num;//再将这个数存入数组
}
}
//这样就不用实现n的自减了(可以直接把j的值当做自减过得n用)
然而残忍的是,费半天劲实现的去重居然没啥用,因为相同的点在这个代码中不会被统计多次
如果出现相同的点,最多只需要标记一个即可
while(i<n){
//假设现在走到了相同的点
int sp=inp[i++];//sp是i(相同点的第一个),此时i自增,指向的是相同点的第二个
while(i<n&&inp[i]<=sp+r){//如果i<n(防数组越界)且这个点在r范围内,i就继续自增
i++;
}
sp=inp[i-1];
while(i<n&&inp[i]<=sp+r){//原理同上,只要这个点还在r的范围内就自增
i++;
}
ans++;//在这里计数,所以上面有几个相同的点都不影响最后的计数
}
咿~~还是写之前一直囿于for循环,怎么写都会导致相同点会自增的原因导致的,不过加了也不会TLE就是了
代码
#include <cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int r,n;
while(scanf("%d %d",&r,&n)!=EOF){
if(r==n&&n==-1){
break;
}
else{
int inp[1010];
int i,j,k;
for(i=0;i<n;i++){
scanf("%d",&inp[i]);
}
sort(inp,inp+n);
int flag=0;
for(i=0;i<n-1;i++){
// if(inp[i]==inp[i+1]){//极为先进的去重部分
// for(k=i;k<n-1;k++){
// inp[k]=inp[k+1];
// }
// n--;
// flag=1;
// }
}
i=0;
int ans=0;
while(i<n){//核心算法了属于是,其实就是一个区间的贪心问题
int sp=inp[i++];
while(i<n&&inp[i]<=sp+r){
i++;
}
sp=inp[i-1];
while(i<n&&inp[i]<=sp+r){
i++;
}
ans++;
}
printf("%d\n",ans);
}
}
}
反思
最开始用for遍历所有点,显然不合适但不会while,代码实现还是有问题,语言啊...
然后是没分析数据导致多了一步去重,还好写了也没超时hhh
最后是算法里面
while(i<n&&inp[i]<=sp+r){
i++;
}
sp=inp[i-1];
while(i<n&&inp[i]<=sp+r){
i++;
}
这一段,最开始while的条件忘了加等号=导致如果有点刚好在sp+r这个位置会被漏掉导致多一次计数
其实真不难,还是太菜了,得多练嗷

浙公网安备 33010602011771号