hdu 4462 Scaring the Birds

枚举子集+模拟

2012国赛简单题。题意有n*n的点,有一些点是空地可以放稻草人保护稻草,稻草人有保护范围,就是距离为r的曼哈顿距离。问要保护所以的草最少要多少个稻草人,输出最少个数,如果全部放入都不能全部保护则输出-1

这题有坑,不过代码写得好的话,坑是可以避免的,不需要特判。1.可以能一个空地都没有即不能放稻草人,所有稻草都无法收到保护,输出-1。2.所有点都是空地,全部放稻草人,这样的话答案是0,因为根本没有草不需要保护。2.注意一点,我就是为此WA了好多次,空地是不需要保护的!比如枚举了放置的稻草人并把受保护的点染色为1,如果有些点为0,并不一定是失败,可能那个点是空地,虽然它没有放稻草人,但是它也是不需要保护的

 

数据规模比较小,直接暴力枚举即可。m个稻草人,枚举放那些其实就是枚举子集,用二进制或者dfs枚举都可以。

#include <cstdio>
#include <cstring>
#define N 55
#define M 15
#define INF 0x3f3f3f3f

struct point
{
  int x,y,r;
}p[M];

bool cover[N][N];
bool mark[N][N];
bool used[M];
int n,m,ans;

int max(int a ,int b)
{ return a>b?a:b; }
int min(int a ,int b)
{ return a<b?a:b; }
int ABS(int a)
{ return a>0?a:-a; }

void input()
{
  memset(mark,false,sizeof(mark));
  scanf("%d",&m);
  for(int i=0; i<m; i++)
  {
    scanf("%d%d",&p[i].x,&p[i].y);
    mark[p[i].x][p[i].y]=true;
  }
  for(int i=0; i<m; i++) scanf("%d",&p[i].r);
}

void judge(int num)
{
  for(int i=1; i<=n; i++)
    for(int j=1; j<=n; j++)
      if(!cover[i][j] && !mark[i][j])
        return ;
  ans=min(ans,num);
}

void COVER(int num)
{
  memset(cover,false ,sizeof(cover));
  for(int i=0; i<m; i++) //枚举每个点
  {
    if(!used[i])  continue; //没有用到这个点
    int x,y,r;
    x=p[i].x; y=p[i].y; r=p[i].r;
    int top,butt,left,right;
    top=max(x-r,1);
    butt=min(x+r,n);
    left=max(y-r,1);
    right=min(y+r,n);

    for(int row=top; row<=butt; row++)
      for(int col=left; col<=right; col++)
        if( ABS(row-x) + ABS(col-y) <= r )
          cover[row][col] = 1;
  }
  judge(num);
}


void solve()
{
  ans=INF;
  int maxs=(1<<m);
  for(int s=0; s<maxs; s++)
  {
    int num,ss;
    ss=s; num=0;
    memset(used,false,sizeof(used));
    for(int i=0; i<m; i++)
      if(ss&(1<<i))
      { used[i]=true; num++;}
    if(num>=ans) continue;
    COVER(num);
  }

  if(ans==INF) printf("-1\n");
  else         printf("%d\n",ans);
}

int main()
{
  while(scanf("%d",&n)!=EOF && n)
  {
    input();
    solve();
  }
  return 0;
}

 

 

计算曼哈顿距离

for(int row=top; row<=butt; row++)
      for(int col=left; col<=right; col++)
        if( ABS(row-x) + ABS(col-y) <= r )
          cover[row][col] = 1;

 

posted @ 2013-03-18 13:01  Titanium  阅读(410)  评论(0编辑  收藏  举报