題意:給定了一個N*N的地圖,地圖上有K(0--10)個點可以放守衛,其它點有食物,每個守衛有一個R,只要其它點的食物到守衛點的曼哈頓距離在R範圍內就算被保護。
問最少需要多少個守衛,使得所有食物都被保護。
看到K最多隻有10,就可以狀態壓縮K的所有情況,枚舉一遍,可行就比較一下。
有個trick:只需要所有的食物被保護就行,空地如果不放守衛未被保護也可以。
#include <iostream>
#include <algorithm>
#include <cmath>
#include<functional>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <climits>//形如INT_MAX一類的
#define MAX 100005
#define INF 0x7FFFFFFF
using namespace std;
int n,k,ans;
int buff[1 << 10];
int vis[55][55];
int mp[55][55];
int dir1[] = {1,1,-1,-1};
int dir2[] = {1,-1,-1,1};
struct node {
int x,y;
int r;
} pos[11];
bool inside(int x,int y) {
if(x > 0 && x <= n && y > 0 && y <= n) return 1;
return 0;
}
void cover(int id) {
int x = pos[id].x;
int y = pos[id].y;
int r = pos[id].r;
for(int dx=0; dx<=r; dx++) {
for(int dy=0; dy<=r-dx; dy++) {
for(int i=0; i<4; i++) {
int xx = x + dir1[i] * dx;
int yy = y + dir2[i] * dy;
if(inside(xx,yy)) vis[xx][yy] = 1;
}
}
}
}
bool judge() {
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++) {
if(vis[i][j] == 0 && mp[i][j] == 0) return 0;
}
}
return 1;
}
void solve() {
int total = 1 << k;
for(int i=0; i<total; i++) {
memset(vis,0,sizeof(vis));
int tmp = i;
int cnt = 0;
int num = 0;
while(tmp) {
if(tmp & 1) {
num ++;
cover(cnt);
}
tmp = tmp >> 1;
cnt ++;
}
if(judge()) {
ans = min(ans,num);
}
}
if(ans == INF) printf("-1\n");
else printf("%d\n",ans);
}
int main() {
while(scanf("%d",&n) && n) {
scanf("%d",&k);
memset(mp,0,sizeof(mp));
for(int i=0; i<k; i++) {
scanf("%d%d",&pos[i].x,&pos[i].y);
mp[pos[i].x][pos[i].y] = 1;
}
for(int i=0; i<k; i++) {
scanf("%d",&pos[i].r);
}
ans = INF;
solve();
}
return 0;
}