hdu 4462稻草人
问题描述:有一块N*N的玉米田(N<=50),给定K个(X,Y)的坐标位置(K<=10)和相应的覆盖范围,请问,至少在这K个位置中选择几个放置稻草人,能保证玉米田全被覆盖?
网上题解:(帮助理解)可放稻草人位置个数m<=10,所以可以状态压缩(就是枚举0~(1<<m)-1。对于枚举的每个数,表示成m位二进制,从右开始,第 几位是1表示放稻草人,否则不放。这样就可以用2^10时间,枚举所有状况,称为状态压缩),枚举所有情况,对于每种情况,遍历所有有玉米的点判断是否可 以被覆盖即可。为什么是枚举所有有玉米点而不是广搜,这就是复杂度的问题了,详细在注意事项内。
#include<iostream> #include<cstring> #include<cmath> using namespace std; int main() { int a; while(cin >> a&& a!= 0) { int b ,count,temp =0,bj = 0; cin >> b; int aa[1000]= {0}; int bb[52][52] = {0}; for(int i =0;i<3*b;i+=3) { cin >> aa[i] >> aa[i+1]; bb[aa[i]][aa[i+1]] = 1; } for(int i =0;i < a;i++) { for(int j =0;j< a;j++) { if(bb[i][j] == 0)bj = 1; } } for(int i =0; i < 3*b;i+=3) { cin >> aa[i+2]; } int ans = 999999,flag; for(int i=0;i<=(1<< b)-1;i++) { flag =0; count =0; for(int j =0,k=0; j<3*b;j+=3,k++) { if(i&(1<<k)) { for(int p =1;p <=a;p++) { for(int q =1;q<=a;q++) { if(abs((double)(p-aa[j]))+abs((double)(q-aa[j+1])) <=aa[j+2]) bb[p][q] = 1; } } flag++; } } for(int p=1; p<=a;p++) { for(int q=1;q<=a;q++) { if(bb[p][q] == 0)count =1; } } if(count==0) { ans = ans < flag?ans:flag; temp= 1; } } if(bj == 0)cout<< "0" << endl; else if(temp == 0) cout<<"-1"<< endl; else cout<< ans<< endl; } return 0; }