题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4462
题意:给你k个稻草人,每个稻草人给出其所在的坐标以及其看守的范围kk,能被其看守的点是到其的所在点的曼哈顿距离<=kk的点。问从中最少选取几个稻草人可以将图上的每个点都看守住。
思路:观察数据发现k很小最大只有10,所以我们可以很暴力的来做,我们枚举放一个,放两个,放三个稻草人的方案,之后再判断是否每个点都被看守了来更新答案,真是相当暴力呀。
ps:此题有一坑点就是这k个稻草人所在的点都是默认被看守的(就算你不选这个稻草人它也是被看守的),北大出题真是有坑呀~~。
code:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define INF 1000000000
using namespace std;
const int maxn=55;
const int maxk=15;
int N,K;
bool pp[maxn][maxn];
struct node
{
int x,y,k;
} P[maxk];
bool jud()
{
bool flag=0;
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
if(!pp[i][j]){
flag=1;
break;
}
}
if(flag) break;
}
return flag;
}
void op(int v)
{
int si,sj,ei,ej;
si=P[v].x-P[v].k<0? 0:P[v].x-P[v].k;
sj=P[v].y-P[v].k<0? 0:P[v].y-P[v].k;
ei=P[v].x+P[v].k>N-1? N-1:P[v].x+P[v].k;
ej=P[v].y+P[v].k>N-1? N-1:P[v].y+P[v].k;
for(int i=si;i<=ei;i++){
for(int j=sj;j<=ej;j++){
if((abs(i-P[v].x)+abs(j-P[v].y))<=P[v].k) pp[i][j]=1;
}
}
}
/*void output()
{
printf("\n");
for(int i=0;i<N;i++){
for(int j=0;j<N;j++) printf("%d ",pp[i][j]);
printf("\n");
}
}*/
int main()
{
int kk,res;
while(scanf("%d",&N),N!=0){
scanf("%d",&K);
res=INF;
for(int i=0;i<K;i++){
scanf("%d%d",&P[i].x,&P[i].y);
P[i].x--;
P[i].y--;
}
for(int i=0;i<K;i++) scanf("%d",&P[i].k);
for(int i=0;i<(1<<K);i++){
kk=0;
memset(pp,0,sizeof(pp));
for(int j=0;j<K;j++) pp[P[j].x][P[j].y]=1;
for(int j=0;j<K;j++){
if(!((i>>j)&1)) continue;
op(j);
kk++;
}
if(!jud()) res=min(res,kk);
}
if(res==INF) printf("-1\n");
else printf("%d\n",res);
}
return 0;
}