状态压缩,K<=10, 0--2^k-1的二进制每一位对应第K个稻草人是否放(0表示不放,1表示放)
注意稻草人坑是不需要覆盖的,全是坑的时候,输出0;(不要问我为什么知道,因为我被坑了4次 T_T)
#include <iostream>
#include <string.h>
using namespace std;
struct pos{
int x,y;
}p[15];
int f[55][55],r[15];
int n,k;
int abs(int a){
if(a<0)return -a;
return a;
}
void change(int b){ //用于把第b个稻草人所包括的范围覆盖
int xx,yy;
int l=r[b];
for(int i=-l;i<=l;i++){
xx=p[b].x+i;
if(xx<1||xx>n)continue;
for(int j=abs(i)-l;j<=l-abs(i);j++){
yy=p[b].y+j;
if(yy<1||yy>n)continue;
f[yy][xx]=1;
}
}
}
void init(){ //初始化
memset(f,0,sizeof(f));
for(int i=0;i<k;i++){
f[p[i].y][p[i].x]=1;
}
}
bool solve(){ //检验是否所有的田地都已经覆盖
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(!f[i][j])return false;
}
}
return true;
}
int main(){
int ans,flag;
while(cin>>n){
if(n==0)break;
cin>>k;
for(int i=0;i<k;i++){
cin>>p[i].y>>p[i].x;
}
for(int i=0;i<k;i++){
cin>>r[i];
}
ans=k+1;
init();
if(solve()){cout<<"0"<<endl;} //都是坑时直接输出0;
else {
for(int i=0;i<(1<<k);i++){
flag=0;
init();
for(int j=0;j<k;j++){
if(i&1<<j){ //状态压缩
change(j);
flag++;
}
}
if(solve()){
if(ans>flag)ans=flag;
}
}
if(ans<=k)cout<<ans<<endl;
else cout<<"-1"<<endl;
}
}
}