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;
}
posted @ 2014-07-23 16:28  TK在颤抖  阅读(145)  评论(1编辑  收藏  举报