• 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;
  • 相关阅读:
    Hznu_0j 1533 计算球体积(水)
    电子警察
    UVA ——利用常量数组
    排序算法
    分解质因数
    几种数
    动态规划
    C. The Football Season (枚举) ( Codeforces Round #592 (Div. 2) )
    Fibonacci前n项和 (矩阵乘)
    2153: D.ly的排队问题 (拓扑排序)(vector , set , priority_queue )
  • 原文地址:https://www.cnblogs.com/scau20110726/p/2965806.html
Copyright © 2020-2023  润新知