题意:有N * N的格子。每个格子上有粮食。但是,现在有些格子的粮食被鸟吃了。现在,我们需要放一些稻草人,来吓鸟。稻草人只能放在没有粮食的地方,一个地方只能放一个稻草人。每个地方的稻草人会给出他能管辖的范围。现在求放最少的稻草人使整个n * n的方格都被看管。
思路:因为能放稻草人的地方至多10个,我们暴力搞搞就可以了。位压枚举放置稻草人的方式,暴力判断是否都覆盖就可以了。
有一个比较坑的地方在于,可能不需要稻草人:如果所有地方都被鸟吃了,那我们就不需要稻草人了。这意味着,我们要从0开始枚举。
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn = 55;
bool m[maxn][maxn];
struct Point
{
int x,y;
}P[15];
int ans;
int R[15];
int n,k;
int total;
int cost;
void makemark(int id)
{
int i,j;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(abs(P[id].x-i)+abs(P[id].y-j)<=R[id] && !m[i][j]) total++,m[i][j]=true;
//printf("%d %d\n",id ,total);
}
void make()
{
int i;
for(i=1;i<=k;i++)
m[P[i].x][P[i].y]=true;
}
void solve(int x)
{
memset(m,false,sizeof(m));
make();
total=k;
int cnt=1;
cost=0;
while(x)
{
if(x&1) cost++,makemark(cnt);
x=x>>1;
cnt++;
}
if(total==n*n) ans=min(ans,cost);
}
int main()
{
//freopen("in","r",stdin);
while(scanf("%d",&n)&&n)
{
int i;
scanf("%d",&k);
for(i=1;i<=k;i++)
scanf("%d %d",&P[i].x,&P[i].y);
for(i=1;i<=k;i++)
scanf("%d",&R[i]);
ans=15;
for(i=0;i<(1<<k);i++)
solve(i);
if(ans==15) printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}