UVA 658 It's not a Bug, it's a Feature! (特殊图最短路)

题意: 修补bug,会引入新的bug。n(n<=20)个bug和m(m<=100)个补丁,每个补丁用两个长度为n的字符串表示,每个位置表示一个bug。一串表示打补丁前的状态(“-”表示该bug必须不存在,“+”表示必须存在,“0”表示无所谓),二串表示打补丁后的状态(“-”表示不存在,“+”表示存在,“0”表示不变)。每个补丁有一个时间,用最少的时间变得没有bug。一个补丁可用多次。

要满足一串的状态才能变成二串的状态。


分析:把状态看做结点,状态转移看做边,然后用spfa求解。

          不需要把图存好,每次取出一个结点,直接枚举m个补丁,看是否能够打得上。

          状态用二进制表示,类似状压dp那样状态压缩。
一串:
    +  存入s[1][i]
    + 和0  存入s[0][i]
二串:
同上,存入t[1][i] 和t[0][i]

 u  |  s[1][i] == u     s[1][i]等于1的地方u也等于1      存在的一定要存在
 u & s[0][i] == u      s[0][i]为0的地方u也必定等于0   不存在的一定要不存在
两个条件合起来满足一串的要求


变成二串状态
v = u;
v |= t[1][i];
v &= t[0][i];




#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
#include<cctype>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<iomanip>
#include<sstream>
#include<limits>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int N= 2000;
const int maxn = 1e3+10;
const int maxm = 2000000001;
const int MOD = 1e6;
int n,m;
int w[110];
int s[2][110],t[2][110];
int dis[1<<25],inq[1<<25];
void spfa(int st)
{
    for(int i = 0;i <= st;i++) dis[i]=inf;
    memset(inq,0,sizeof(inq));
    queue<int> Q;
    dis[st] = 0;
    inq[st] = 1;
    Q.push(st);
    while(!Q.empty())
    {
        int u = Q.front(); Q.pop();
        inq[u] = 0;
        for(int i = 0;i < m;i++)
           if( ((u | s[1][i]) == u) && ((u & s[0][i]) == u) )  //是否满足一串状态
            {

                int v = u;
                v |= t[1][i];
                v &= t[0][i];               //变成二串状态
                if(dis[u] + w[i] < dis[v])
                {
                    dis[v]=dis[u]+w[i];
                    if(!inq[v])
                    {
                        Q.push(v);
                        inq[v]=1;
                    }
                }
            }
    }
}
char a[25],b[25];
int main(){
#ifdef LOCAL
	freopen("C:\\Users\\lanjiaming\\Desktop\\acm\\in.txt","r",stdin);
	//freopen("output.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
	int kase =0;
	while (cin>>n>>m && (n+m))
	{
       cout<<"Product "<<++kase<<endl;
        memset(s,0,sizeof(s));
        memset(t,0,sizeof(t));
        for(int i = 0;i < m;i++)
        {
            cin>>w[i]>>a>>b;
            for(int 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);
            }
       }
        spfa((1<<n)-1);
        if(dis[0] == inf) cout<<"Bugs cannot be fixed.\n";
        else  cout<<"Fastest sequence takes "<<dis[0]<<" seconds.\n";
       cout<<endl;
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值