1. 程式人生 > >It's not a Bug, it's a Feature!-----------優先佇列和spfa----做了很長時間!!!(好題!)

It's not a Bug, it's a Feature!-----------優先佇列和spfa----做了很長時間!!!(好題!)

可以直接用位運算去操作:

    ①判定某些位置是否為1,如判定2、4位置為1,則轉化為判斷x|0101是否等於x。

    ②判定某些位置是否為0,如判定2、4位置為0,則轉化為判斷x&1010是否等於x。

    ③將某些位置轉化為1,如2、4位置轉化為1,則令x=x|0101。

    ④將某些位置轉化為0,如2、4位置轉化為0,則令x=x&1010。

    在用二進位制表示狀態的基礎上採用這些位運算技巧之後,速度就變得比較快了。

用了兩種方法(優先佇列和spfa)

#include<cstdlib>
#include<iostream>
#include<sstream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include <algorithm>
#include<vector>
#include<set>
#include<queue>
#define LL long long
#define inf 1000000000
#define E 1e-9
#define N 100
#define M 2000000
using namespace std;
int n,m,ans;
char str1[25],str2[25];
int map[110][2][2],w[110];
int v[2000000];
typedef pair<int,int> pii;
priority_queue<pii,vector<pii>,greater<pii> > q;
int d[2000000],qu[2000000],inq[2000000];
void print(int p)
{
//    for(int i=0; i<n; i++)
//        if(p&(1<<i))
//            cout<<"1";
//        else
//            cout<<"0";

}
void spfa()
{
    int r=0,f=0;
    int MAX=(1<<n);
    for(int i=0; i<MAX; i++)
    {
        d[i]=inf;
        inq[i]=0;
    }
    d[MAX-1]=0;
    qu[r++]=MAX-1;
    inq[MAX-1]=1;
    while(f<r)
    {
        int u=qu[f++];
        if(f==M-1)
            f=0;
        inq[u]=0;
        for(int i=0; i<m; i++)
        {
            int t=u;
            if((t|map[i][0][0])==t&&(t&map[i][0][1])==t)
            {
                t|=map[i][1][0];
                t&=(map[i][1][1]);

                if(d[t]>d[u]+w[i])
                {
                    d[t]=d[u]+w[i];
                    if(!inq[t])
                    {
                        inq[t]=1;
                        qu[r++]=t;
                        if(r==M-1)
                            r=0;
                    }
                }
            }
        }
    }

}
int dfs()
{
    while(!q.empty())
        q.pop();
    q.push(make_pair(0,(1<<n)-1));
    while(!q.empty())
    {
        pii u=q.top();
        q.pop();
        int p=u.second;
        v[p]=1;//只有出佇列時,才說明不用在考慮他了!!!!
        if(!p)
            return u.first;
        for(int i=0; i<m; i++)
        {
            int t=p;
            if((t|map[i][0][0])==t&&(t&map[i][0][1])==t)
            {
                t|=map[i][1][0];
                t&=(map[i][1][1]);
                if(v[t])
                    continue;
                q.push(make_pair(u.first+w[i],t));
            }
        }
    }
    return -1;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("ex.in","r",stdin);
#endif
    int ncase=0;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(!n&&!m)
            break;
        memset(v,0,sizeof(v));
        memset(map,0,sizeof(map));
        for (int i=0; i<m; i++)
        {
            scanf("%d%s%s",&w[i],str1,str2);
            for(int j=0; j<n; j++)
            {
                if(str1[j]=='+')
                {
                    map[i][0][0]+=(1<<j);///////////////////
                }
                if(str2[j]=='+')
                {
                    map[i][1][0]+=(1<<j);
                }
                if(str1[j]!='-')
                {
                    map[i][0][1]+=(1<<j);
                }
                if(str2[j]!='-')
                {
                    map[i][1][1]+=(1<<j);
                }

            }

        }
        int flag=dfs();
//        spfa();
        printf("Product %d\n",++ncase);
//        if(d[0]==inf)
        if(flag==-1)
            printf("Bugs cannot be fixed.\n");
        else
            printf("Fastest sequence takes %d seconds.\n",flag);
//            printf("Fastest sequence takes %d seconds.\n",d[0]);

        printf("\n");
    }

    return 0;
}