hdu 4462 Scaring the Birds 状压枚举 (或dfs)

     长度宽度都为n的正方形田地种满了玉米,其中一些点的玉米被野怪吃掉了变成了空地... 在不同的空地安插一个稻草人,可以保护与这个点曼哈顿距离小于ki的点。给出空地的坐标,问最少要多少个稻草人可以保护所有非空地的点。一眼看上去就知道是个水题..开始被题意坑了好久,以为要把整个正方向全覆盖,结果WA到死。最后发现只要覆盖非空地的点就行了....空地数量不超过10,直接枚举1024种状态,或者直接DFS都行吧。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <memory.h>
#include <cmath>
#include <string>
#include <cstring>
#include <queue>
#include <map>
#include <stack>
using namespace std;
typedef long long ll;
struct node
{
    int x,y,range;
}dc[15];
int n,m,p,q,x,y;
int tt;
int ans;
bool on[15];
bool site[55][55];
bool check(int x,int y)
{
    if (x>=1 && y>=1 && x<=n && y<=n) return true;
    return false;
}
void go(int x1,int y1,int x2,int y2,int fx,int fy)
{
    while(x1!=x2 && y1!=y2)
    {
        if (check(x1,y1)) site[x1][y1]=true;
        x1+=fx;
        y1+=fy;
    }
}
bool work(int sta)
{
    memset(on,false,sizeof on);
    memset(site,false,sizeof site);
    for (int i=1; i<=m; i++)
    site[dc[i].x][dc[i].y]=true;

    int x1,x2,x3,x4,y1,y2,y3,y4;
    for (int i=1; i<=m; i++)
    {
        on[i]=sta&1;
        sta>>=1;
    }
    for (int i=1; i<=m; i++)
    {
        if (on[i])
        {
            site[dc[i].x][dc[i].y]=true;
            for (int j=1; j<=dc[i].range; j++)
            {
                x1=dc[i].x-j;
                x2=x4=dc[i].x;
                x3=dc[i].x+j;
                y1=y3=dc[i].y;
                y2=dc[i].y-j;
                y4=dc[i].y+j;
                go(x1,y1,x2,y2,1,-1);
                go(x2,y2,x3,y3,1,1);
                go(x3,y3,x4,y4,-1,1);
                go(x4,y4,x1,y1,-1,-1);
            }
        }
    }

    for (int i=1; i<=n; i++)
     for (int j=1; j<=n; j++)
     if (!site[i][j]) return false;
     return true;
}
int main()
{
//    freopen("in.txt","r",stdin);
    while(~scanf("%d",&n) && n)
    {
        scanf("%d",&m);
        for (int i=1; i<=m; i++)
        scanf("%d%d",&dc[i].x,&dc[i].y);
        for (int i=1; i<=m; i++)
        scanf("%d",&dc[i].range);
        bool ok=false;
        int res=0,ans=1000;
        for (int sta=0; sta<(1<<m); sta++)
        {
            res=0;
            ok=false;
            if (work(sta))
            {
                ok=true;
            }
            if (ok)
            {
                for (int i=1; i<=m; i++)
                {
                    if (on[i]) res++;
                }
                ans=min(ans,res);
            }
        }

        if (ans<=10) printf("%d\n",ans);
        else printf("-1\n");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值