隐式图的最短路径 题目看了老久
要修复所有的漏洞 每个补丁需要一定条件才能打(第一个字符串 第i个字符是+ 说明当前状态一定要有第i个漏洞才能装 - 就是一定没有 o可有可无) 打了可能会导入 或者去掉漏洞(第二个字符串)
从1111(n个1)开始做SPFA 终点是00000(n个0)都用2进制表示
然后是否能使用补丁需要判断 用位运算处理
使用补丁后的状态用一个2进制表示
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
struct node
{
int time;
int s1;
int s2;
int e1;
int e2;
}a[110];
int n,m;
int dis[2000000];
bool vis[2000000];
void SPFA()
{
int i;
int s = (1 << n) - 1;
for(i = 0;i < s; i++)
dis[i] = 999999999;
dis[s] = 0;
memset(vis,false,sizeof(vis));
queue <int> q;
q.push(s);
while(!q.empty())
{
int p = q.front();
q.pop();
vis[p] = false;
for(i = 1;i <= m; i++)
{
int t1 = p | a[i].s1;
int t2 = p & a[i].s2;
if(t1 == p && t2 == p)
{
int t;
t = p | a[i].e1;
t = t & a[i].e2;
if(dis[t] > dis[p] + a[i].time)
{
dis[t] = dis[p] + a[i].time;
if(!vis[t])
{
vis[t] = true;
q.push(t);
}
}
}
}
}
}
int main()
{
char s1[100];
char s2[100];
int i,j,k;
int cas = 1;
while(scanf("%d %d",&n,&m),n||m)
{
for(i = 1;i <= m; i++)
{
scanf("%d %s %s",&a[i].time,s1,s2);
a[i].s1 = a[i].s2 = a[i].e1 = a[i].e2 = 0;
for(j = 0,k = n-1; j < n; j++,k--)
{
if(s1[j] == '+')
a[i].s1 += (1<<k);//+的位置都是1
if(s1[j] != '-')
a[i].s2 += (1<<k);//-的位置都是0
}
for(j = 0,k = n-1; j < n; j++, k--)
{
if(s2[j] == '+')
a[i].e1 += (1<<k);
if(s2[j] != '-')
a[i].e2 += (1<<k);
}
//printf("%d %d %d %d\n",a[i].s1,a[i].s2,a[i].e1,a[i].e2);
}
SPFA();
printf("Product %d\n",cas++);
if(dis[0] == 999999999)
printf("Bugs cannot be fixed.\n");
else
printf("Fastest sequence takes %d seconds.\n",dis[0]);
printf("\n");
}
return 0;
}