关键词 :贪心 排序 结构体
一 题解
贪心这种题目真是尴尬……样例过了算法还是有可能不对
做贪心首先要证明正确性啊,感觉自己因为知道是贪心的题目,根本就没怎么考虑就开始做了,做完了发现自己的算法似乎不是对的……
找了一份题解,思路是和我一样的,按照x轴坐标排序之后,从最左边的点,开始计算,尽可能的使每次标记的雷达靠右。
链接:http://www.cnblogs.com/deliver/p/3330801.html
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include <iostream> 2 using namespace std; 3 #include <math.h> 4 5 struct island 6 { 7 int x; 8 int y; 9 }; 10 11 void quick_sort(island *islands,int start,int end,int d); 12 int partition(island *islands,int start,int end,int d); 13 bool smaller_than(island *is1,island *is2,int d); 14 15 void sort(island *islands,int n,int d) 16 { 17 quick_sort(islands,0,n-1,d); 18 } 19 20 void quick_sort(island *islands,int start,int end,int d) 21 { 22 if(start>=end) return; 23 int mid=partition(islands,start,end,d); 24 quick_sort(islands,start,mid-1,d); 25 quick_sort(islands,mid+1,end,d); 26 } 27 28 int partition(island *islands,int start,int end,int d) 29 { 30 int front,back,dir=0; 31 island tis=islands[start]; 32 33 front=start; 34 back=end; 35 while(front<back) 36 { 37 if(dir==0) 38 { 39 if(!smaller_than(&tis,islands+back,d)){ 40 islands[front].x=islands[back].x; 41 islands[front].y=islands[back].y; 42 front++; 43 dir=1; 44 } 45 else back--; 46 } 47 else 48 { 49 if(smaller_than(&tis,islands+front,d)){ 50 islands[back].x=islands[front].x; 51 islands[back].y=islands[front].y; 52 back--; 53 dir=0; 54 } 55 else front++; 56 } 57 } 58 islands[front].x=tis.x; 59 islands[front].y=tis.y; 60 return front; 61 } 62 63 bool smaller_than(island *is1,island *is2,int d) 64 { 65 double v1=is1->x+sqrt(double(d*d-is1->y*is1->y)),v2=is2->x+sqrt(double(d*d-is2->y*is2->y)); 66 return v1<v2; 67 } 68 69 70 int place_radar(island *islands,int n,int d) 71 { 72 int i,counter=0; 73 double rx,ry=0; 74 i=0; 75 while(i<n) 76 { 77 rx=islands[i].x+sqrt(double(d*d-islands[i].y*islands[i].y)); 78 counter++; 79 i++; 80 if(i>=n) break; 81 while((rx-islands[i].x)*(rx-islands[i].x)+(ry-islands[i].y)*(ry-islands[i].y)<=d*d) 82 { 83 i++; 84 if(i>=n) break; 85 } 86 } 87 return counter; 88 } 89 90 int main() 91 { 92 //freopen("data.txt","r",stdin); 93 94 int i,n,d,counter=1,result; 95 96 cin>>n>>d; 97 while(n!=0||d!=0) 98 { 99 island *islands=new island[n]; 100 for(i=0;i<n;i++) cin>>islands[i].x>>islands[i].y; 101 102 bool flag=true; 103 for(i=0;i<n;i++) if(islands[i].y>d) {flag=false; break;} 104 if(d<0) flag=false; 105 106 if(!flag) result =-1; 107 else{ 108 sort(islands,n,d); 109 result=place_radar(islands,n,d); 110 } 111 112 cout<<"Case "<<counter<<": "<<result<<endl; 113 delete []islands; 114 counter++; 115 cin>>n>>d; 116 } 117 118 119 return 0; 120 }
但是我仔细考虑了一下,是可以举出反例证明这种算法不正确的。
如果只有如下两个点的话,因为每次都尽可能地使安排的雷达的坐标靠右,所以对于这两个点按照上述算法是需要两个雷达的。但是事实上只要雷达的坐标稍微向左一点,就可以仅设置一个雷达就覆盖这两个点,所以该算法不成立。
至于上面的代码为什么可以AC……这就是个尴尬的问题了。
感觉自己的代码和上面的代码大同小异,但是就是一直WA,自己感觉也找不出来什么错了,所以就把代码贴出来,如果高手看到,帮我找找错吧,谢谢啦。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include <iostream> 2 #include <algorithm> 3 #include <math.h> 4 using namespace std; 5 6 struct Point{ 7 int x; 8 int y; 9 // int f; 10 }; 11 12 bool compare(Point a,Point b){ 13 return a.x<b.x; 14 } 15 16 int main() 17 { 18 Point p[1000]; 19 int d,n,flag=0,m=0; 20 while(cin>>n>>d,n||d){ 21 if (n==0&&d==0) exit(0); 22 flag=0;m++; 23 if (n==0) {cout<<"Case "<<m<<": "<<0<<endl;continue;} 24 if (d<0) {cout<<"Case "<<m<<": "<<-1<<endl;continue;} 25 26 int i; 27 for(i=0;i<n;i++){ 28 cin>>p[i].x>>p[i].y; 29 if((p[i].y>d)&&(p[i].y<0)) {flag=1;break;} 30 // p[i].f=0; 31 } 32 if (flag) {cout<<"Case "<<m<<": "<<-1<<endl;continue;} 33 34 sort(p,p+n,compare); 35 int ans=0;i=0; 36 double w,t; 37 while(i<n){ 38 double hehe=d*d-p[i].y*p[i].y; 39 w=sqrt(hehe)+p[i].x; 40 i++; 41 ans++; 42 while(i<n){ 43 44 t=(p[i].x-w)*(p[i].x-w)+p[i].y*p[i].y; 45 if(t<=d*d){ 46 // p[i].f=1; 47 i++; 48 }else break; 49 } 50 }//while 51 52 cout<<"Case "<<m<<": "<<ans<<endl; 53 } 54 55 return 0; 56 }
隔了一天又看了一个题解:
http://www.cnblogs.com/deliver/p/3330801.html
二 排序函数
因为太久没撸这些代码了,所以好多小的知识点都忘了,我一点一点补充吧。
1 基本
头文件:#include <algorithm>
函数:sort(begin,end),表示升序排列一个范围,例如:
int a[20]={2,4,1,23,5,76,0,43,24,65},i;
for(i=0;i<20;i++) cout<<a[i]<<endl;
sort(a,a+20);
for(i=0;i<20;i++) cout<<a[i]<<endl;
2 降序排列
一种是自己编写一个比较函数来实现,接着调用三个参数的sort:sort(begin,end,compare)就成了。对于list容器,这个方法也适用,把compare作为sort的参数就可以了,即:sort(compare).
1)自己编写compare函数:
bool compare(int a,int b){
return a<b; //升序排列,如果改为return a>b,则为降序
}
int a[20]={2,4,1,23,5,76,0,43,24,65},i;
for(i=0;i<20;i++) cout<<a[i]<<endl;
sort(a,a+20,compare);
for(i=0;i<20;i++) cout<<a[i]<<endl;
3)其实对于这么简单的任务(类型支持“<”、“>”等比较运算符),完全没必要自己写一个类出来。标准库里已经有现成的了,就在functional里,include进来就行了。functional提供了一堆基于模板的比较函数对象。它们是(看名字就知道意思了):equal_to<Type>、not_equal_to<Type>、greater<Type>、greater_equal<Type>、less<Type>、less_equal<Type>。对于这个问题来说,greater和less就足够了,直接拿过来用:
升序:sort(begin,end,less<data-type>());
降序:sort(begin,end,greater<data-type>()).
int _tmain(int argc, _TCHAR* argv[])
{
int a[20]={2,4,1,23,5,76,0,43,24,65},i;
for(i=0;i<20;i++)
cout<<a[i]<<endl;
sort(a,a+20,greater<int>());
for(i=0;i<20;i++)
cout<<a[i]<<endl;
return 0;
}
4)既然有迭代器,如果是string 就可以使用反向迭代器来完成逆序排列,程序如下:
#include <function>
int main()
{
string str("cvicses");
string s(str.rbegin(),str.rend());
cout << s <<endl;
return 0;
}
三 结构体(C++)
C和C++中的结构体还是有一点点区别,具体不说了,下面是C++版的。
- 声明
struct Stu{
int num;
char name[20];
}
2. 定义
先声明后定义
struct Stu{
int num;
char name[20];
};
Stu s1,s2;
声明同时定义
struct Stu{
int num;
char name[20];
}st1,st2;
3.结构体数组
Stu a[10];