saruman's army
1,一个点从一个属性变成三个属性中,
2,先要简化问题。从最简单的先开始推。
3,挺短的,相应的思维难度也高一些。
4,顺着自己节奏往下吧
#include<iostream> #include<algorithm> using namespace std; const int maxn=1005; int n,r; int a[maxn]; int main(){ cin>>n>>r; for(int i=0;i<n;i++) cin>>a[i]; sort(a,a+n); int i=0,ans=0; while(i<n) { int s=a[i++];//最左边点的位置 while(i<n&&a[i]<=s+r) i++; int p=a[i-1]; while(i<n&&a[i]<=p+r) i++; ans++; } cout<<ans<<endl; }
5,写完该干啥来着。
6,该费大了。费大上来看,你要抽象出来东西,让后再去类比想东西!有点像油滴拓展。一维还是二维,一维也行,二维好像也行,毕竟二维的话其他地方也没东西。
类比的话导弹防御范围可以,雨伞模型也也可。雨伞更形象一点好吧。
至于算法分析的话,有两个方面的,首先第一个肯定是不一样的,在分析第一个的时候,右边范围的最后一个作为标记的点。但是在之后的话,就是右边范围之外的第一个。额我感觉你还是没有抽象出来这个东西。所以说抽象东西要是要技巧的,否则你只在这里蛮干。我觉得吧,一定先要抽象出那些东西,抽象出来的东西自然是最简单的,最朴素的东西。我的右边是上一个的左边。
N个点,每个点都具有一个唯一确定它们自身的属性。现在我们具有能力去赋给某些点特殊的属性,我们选择赋给的点的点数希望是最小的。那么我们选择赋给的策略就要正确。怎么样的策略才能让赋给的点数最小呢?选择的点都是能够覆盖最多的点。
继续从左边分析,从左边第一个点开始的话,选择的点必须在r的范围内,为什么呢?因为你要把最左边的点覆盖掉。那接下来呢?我们要选择的是,从我标记的点开始,向右r范围内之外的第一个点为什么是之外呢?因为我现在右边就是我我该标记的点已经能够覆盖的点了。所以覆盖必然会有交叉(当然也可能有足够完美的数据)另外雨伞模型是可以的,不过你要上下排列一下。导弹自然也是可以的。不过为什么这样就会有最少的点数呢?贪心法?
抽象也不能太抽象,否则失去了这个题本身的意义。所以我费大防空导弹。为了守卫国家,必须要我们的防空导弹覆盖该条战线上的每个居民点。所以我们安装防空导弹的策略是能覆盖到的最后一个点,能覆盖到的之外的第一个点。
噢终于总计了这个题的关键
至于费小,那估计得老老实实用样例推一遍。唉,样例过了一遍没什么太大的发现。不够是不是因为你模拟样例的时候没有思考。
原来我想错了
经过我的模拟,发现我错了,之前想的错了。它其实是,你懂第一个点怎么找的,那你就懂其他怎么找的。
其实相当于在重复一个过程。一个开始的点,一个标记的点。
#include<iostream> #include<algorithm> using namespace std; const int maxn=1005; int n,r; int a[maxn]; int i=0,ans=0; int main(){ cin>>n>>r; for(int i=0;i<n;i++) cin>>a[i]; sort(a,a+n); while(i<n) { int s=a[i++]; //我觉得i++可能是为了抵抗后面那个i-1; //另外i++也是为了计算下一个点看覆盖了没呗。 cout<<"测试1"<<s<<endl; while(i<n&&a[i]<=s+r) i++; int p=a[i-1];//这块错了,i-1,但是不代表变了。 //同时这个P已经是标记的点了 while(i<n&&a[i]<=p+r) i++; //现在这个i是标记的点在右边覆盖之内的最后一个点, //不可能着全错了,你这个条件满足了,i才会加加,这个加已经把它加到下一个点了。 //所以这个i点是右边覆盖之外的第一个点。 ans++; } cout<<ans<<endl; }