[二进制位运算状态 隐式图搜索]UVa658 - It's not a Bug, it's a Feature!

9 篇文章 0 订阅

用二进制表示状态运算起来更快一些,这样一行就可以用一个数字去表示其状态了。按这个思路继续想下去就是如何建图了,其实无论邻接表还是邻接矩阵貌似建完整图的时间复杂度都比较大,而且好多状态未必用的到,因而不如干脆不建完整图,每次都扫描一遍转换规则,如果可以生成另一个状态就将另一个状态直接入队即可。


①判定某些位置是否为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。

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 30;
const int MAXM = 110;
const int MAXD = 2000000;
const int INF = 0x3f3f3f3f;
int s[2][MAXM], t[2][MAXM],w[MAXM], N, M;
char a[MAXN], b[MAXN];
int q[MAXD], inq[MAXD], d[MAXD];
int init(){
    int i,j;
    scanf("%d%d",&N,&M);
    if(!N && !M){
        return 0;
    }
    memset(s,0,sizeof(s));
    memset(t,0,sizeof(t));
    for(i=0;i<M;i++)
    {
        scanf("%d%s%s",&w[i],a,b);
        for(j=0;j<N;j++){
            if(a[j]=='+')
                s[1][i]+=(1<<j);
            if(a[j]!='-')
                s[0][i]+=(1<<j);
            if(b[j]=='+')
                t[1][i]+=(1<<j);
            if(b[j]!='-')
                t[0][i]+=(1<<j);
        }
    }
    return 1;
}
void SPFA(){
    int i,j,k,MAX,front ,rear,u,v;
    MAX=1<<N;
    for(i=0;i<MAX;i++){
        d[i]=INF;
        inq[i]=0;
    }
    front = rear =0;
    d[MAX  - 1]=0;
    q[rear++] = MAX-1;
    while(front != rear){
        u=q[front ++];
        if(front > MAX) front =0;
        inq[u]=0;
        for(i=0;i<M;i++){
            if((u|s[1][i])==u&&(u&s[0][i])==u)
            {
                v=u;
                v|=t[1][i];
                v&=t[0][i];
                if(d[u]+w[i]<d[v]){
                    d[v]=d[u]+w[i];
                    if(!inq[v]){
                        q[rear++]  = v;
                        if(rear > MAX) rear =0;
                        inq[v]=1;
                    }
                }
            }
        }

    }
    if(d[0]==INF)
        printf("Bugs cannot be fixed.\n");
    else
        printf("Fastest sequence takes %d seconds.\n", d[0]);
}
int main()
{
    int T=0;
    while(init()){
        printf("Product %d\n",++T);
        SPFA();
        printf("\n");
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值