UVA

来源:互联网 发布:php eval 执行函数 编辑:程序博客网 时间:2024/06/11 17:33

题目链接:点击打开链接

题意参见《算法竞赛入门经典(第二版)》(紫皮)P.365

思路:

可以将补丁的前后状态理解为边的起点和终点,这样就能抽象为求最短路径。这里我用了spfa,但是一开始没有解决状态压缩的问题,所以一直超时。后来发现状态压缩时根本不用考虑'0',只需要考虑'-'、'+'就可以了,于是就可以用二进制来状态压缩,最大规模不超过二百万。于是就可以愉快的spfa了。

代码:

#include<stdio.h>#include<string.h>#include<queue>#include<algorithm>#include<map>using namespace std;#define inf 1<<29int n,m;int w[105];char u[105][22],v[105][22],goal[22];int dis[2500000];struct node{    char state[22];    int step;}p;int match(char a[],char b[]){    for(int i=0;i<n;i++)    {        if(b[i]!='0' && a[i]!=b[i]) return 0;    }    return 1;}int ahash(char a[]){    int h=0;    for(int i=0;i<n;i++)    {        if(a[i]=='-') h=(h<<1);        else if(a[i]=='+') h=(h<<1)+1;    }    return h;}int bfs(){    int h;    queue<node> q;    memset(dis,-1,sizeof dis);    for(int i=0;i<n;i++)        p.state[i]='+';    p.state[n]=0;    h=ahash(p.state);    dis[h]=0;    p.step=0;    q.push(p);    while(!q.empty())    {        node top=q.front(); q.pop();        for(int i=0;i<m;i++)        {            if(match(top.state,u[i]))            {                for(int j=0;j<n;j++)                {                    if(v[i][j]!='0') p.state[j]=v[i][j];                    else p.state[j]=top.state[j];                }                p.state[n]=0;                h=ahash(p.state);                p.step=top.step+w[i];                if(dis[h]!=-1 && p.step>=dis[h]) continue;                dis[h]=p.step;                q.push(p);            }        }    }    return dis[ahash(goal)];}int main(){    int cas=0;    while(scanf("%d%d",&n,&m) && n+m)    {        for(int i=0;i<m;i++)            scanf("%d%s%s",&w[i],u[i],v[i]);        for(int i=0;i<n;i++)            goal[i]='-';        goal[n]=0;        int ans=bfs();        printf("Product %d\n",++cas);        if(ans==-1)            printf("Bugs cannot be fixed.\n\n");        else            printf("Fastest sequence takes %d seconds.\n\n",ans);    }    return 0;}


原创粉丝点击