您的位置:首页 > Web前端

hdu 1818 hdu 1818 It's not a Bug, It's a Feature!(位运算+bfs优先队列)

2013-07-10 23:59 344 查看
题意:给一个长度为n的bug,和m个补丁,然后是m个补丁的描述。第一个数字是这个补丁消耗的时间。

第1个字符串是这个补丁要工作需要满足的条件,第2个字符串是这个补丁的作用

详细一点说,

对于第一个字符串,假设是 -0-+0。 -号代表这个位的bug不能出现,也就是不能有3号和5号bug。(定义最右边为1号,为了到时候方便位运算) +号就是指这个位bug一定要出现,也就是一定要有2号bug。0就是指……没什么意思。

满足上述条件该补丁才能起作用。

对于第二个字符串,假设是00--+,-号代表这个补丁能杀掉这个位的bug,也就是杀掉2,3号。+号代表这个补丁会带来这个位的bug,也就是会新产生一个1号bug。

(假设bug长度为n,那么起始的时候,是1-n位都有bug,我们可以用一个二进制1111...1来表示)

解法:扩展状态的时候可以用位运算,容易理解又加快时间,具体的是&,|,~什么的,就请读者自己分析下吧(提示:不能出现的,必须出现的,能杀掉的,新产生的,4者单独储存)

题意理解后,很容易发现是一个单次消耗值不同的宽搜,对于这种题目,不像迷宫题,每次消耗值都是固定的。这种消耗值不固定的题目,一般都要使用优先队列,将当前消耗值最低的先出列扩展。而且,当扩展的时候找到最终答案时,也不能立即返回,因为即使是优先队列,也不能保证最后那个值是最低的。

举个例子 队列里

A-----B-----C 队头

现在C的值最低,由它扩展,假设C可以直接扩展到答案,那么它的消耗值就是 C+X,如果此时return,就可能丢失掉最优解。

因为,如果B出列,B也可以直接扩展到答案,那么它的消耗值是 B+Y,根据优先队列,C<B,但我们不能保证X<Y,所以有可能B+Y<C+X。

#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;

int n,m;
int v[1100005];
struct node
{
    int yes;
    int no;
    int kill;
    int add;
    int time;
}tr[105];

struct node1
{
    int bug;
    int step;
    bool operator < (const node1 &a)const
    {
        return step > a.step;
    }
};

priority_queue <node1> Q;

bool ok(int bug,node t)
{
    if((t.no&bug)!=0)return false;
    if((t.yes&bug)!=t.yes)return false;

    return true;

}

int fix(int bug,node t)
{
    int tmp=bug;
    bug=((~t.kill)&bug);
    bug=(t.add|bug);

    if(tmp==bug)return -1;

    return bug;
}

void bfs()
{
    node1 w,e;
    while(!Q.empty())
    {
        w=Q.top();
        Q.pop();
        if(w.bug==0){printf("Fastest sequence takes %d seconds.\n",w.step);return;}
        //cout<<"----"<<endl;
        for(int k=0;k<m;k++)
        {
            e=w;
            if(ok(w.bug,tr[k]))
            {
                e.bug=fix(e.bug,tr[k]);
                if(e.bug<0)continue;
                e.step += tr[k].time;

                if(v[e.bug]!=-1 && e.step >= v[e.bug])continue;

                v[e.bug] = e.step;
                Q.push(e);
            }
        }
    }
    printf("Bugs cannot be fixed.\n");
}

int main()
{
    char a[200],b[200];
    node1 w;
    int CASE=1;
    while(scanf("%d%d",&n,&m)!=EOF && n && m)
    {
        int g = 0;
        g = (1 <<n) - 1;
        memset(v,-1,sizeof(v));
        memset(tr,0,sizeof(tr));

        while(!Q.empty())Q.pop();

        for(int i=0;i<m;i++)
        {
            scanf("%d %s %s",&tr[i].time,a,b);
            {
                //printf("a = %s\n b = %s\n",a,b);
                for(int j=0;j<n;j++)
                {
                    if(a[j]=='+')
                    tr[i].yes+=(1<<(n-j-1));
                    else if(a[j]=='-')
                    tr[i].no+=(1<<(n-j-1));
                }
                for(int j=0;j<n;j++)
                {
                    if(b[j]=='+')
                    tr[i].add+=(1<<(n-j-1));
                    else if(b[j]=='-')
                    tr[i].kill+=(1<<(n-j-1));
                }
            }
        }
        w.bug = g;
        w.step=0;
        Q.push(w);
        printf("Product %d\n",CASE++);
        bfs();
        putchar(10);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: