一道关于状态压缩的题目。
状态压缩主要用于01类型选择的题目,因为用二进制表示数
的时候,某一位不是0,就会是1,所以可以利用二进制的这种特性
模拟不同的状态。
这道题目还要注意一下位运算的使用。
代码如下:
//恰好从0--2^k-1中的每个数
//的二进制表示都可以表示一种摆放的方法
//所以只需穷举这个范围内的每个数,在对应看这个数
//对应的方法能发覆盖;当然因为穷举的时候没有从多到少
//所以需要将所有的情况穷举出来再做比较,求出最小的情况
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int visited[55][55],n,k,d[15];
typedef struct
{
int x,y;
}M;
M m[15];
void search(int k) //第k个位置放置稻草人
{
int i,j;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(abs(i-m[k].x)+abs(j-m[k].y)<=d[k]) //可以覆盖则标记为1(注意判断距离方法)
visited[i][j]=1;
}
int check()
{
int i,j;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(!visited[i][j])
return 0;
return 1; //所有的点都被标记后返回1
}
int main()
{
int i,j,min,cnt,m1;
while(scanf("%d",&n)&&n)
{
min=99999;
scanf("%d",&k);
for(i=1;i<=k;i++)
scanf("%d%d",&m[i].x,&m[i].y);
for(i=1;i<=k;i++)
scanf("%d",&d[i]);
for(i=0;i<=(1<<k)-1;i++)
{
cnt=1;m1=0;
memset(visited,0,sizeof(visited));
for(int i1=1;i1<=k;i1++) //放置稻草人的位置无需覆盖,直接标记为1
{
int x=m[i1].x;
int y=m[i1].y;
visited[x][y]=1;
}
j=i;
while(j)
{
if(j&1)
{
search(cnt);
m1++; //m1记录放置个数
}
cnt++;
j=j>>1;
}
if(check())
if(min>m1)
min=m1;
}
if(min==99999) //如果没有能够覆盖
cout<<"-1"<<endl;
else
cout<<min<<endl;
}
return 0;
}