1.题目描述:点击打开链接
2.解题思路:本题要求找最短的时间,乍一看想用动态规划解决,但可惜这种做法是行不通的,因为状态经过多次转移之后可能会回到原先的状态,即状态图不是DAG。因此联想到用图论上的最短路算法来解决。先把每个状态都看成一个结点,然后用Dijkstra算法解决即可,不过本题与普通的最短路问题略有不同:结点很多,多达2^n个,而且很多状态根本遇不到。所以没必要先把图储存好。(一般的Dijkstra算法用之前都储存好了图)
这里可以直接枚举这m个补丁,看哪一个能用,这样既就能不断地拓展结点了。初始状态是(1<<n)-1,最终的状态是0。本题最终答案是d[0]。本题的一个技巧是先把打补丁之前的状态中必须有的bug用集合来表示,再把无所谓的bug也表示出来,都放到pre数组;用同样的方法预处理打补丁后的状态,放到Next数组中。这样后面的一系列结点就能通过集合之间的运算拓展出来了。
3.代码:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<functional>
using namespace std;
#define N 21
#define M 101
const int INF = 500000000;
int pre[2][M], Next[2][M];//pre数组存放之前的状态,Next数组存放之后的状态
int t[M];
int d[1 << N];
typedef pair<int, int> P;
void dijkstra(int n, int m)//求最短路
{
for (int i = 0; i < (1 << n); i++)
d[i] = INF;
priority_queue<P, vector<P>, greater<P> >q;
d[(1 << n) - 1] = 0;//全部bug都存在为初始状态
q.push(P(0, (1 << n) - 1));
while (!q.empty())
{
P u = q.top(); q.pop();
int x = u.second;
if (u.first != d[x])continue;
for (int i = 0; i < m;i++)
if ((x | pre[0][i]) == x &&(x&pre[1][i]) == x)//枚举所有m个补丁,看是否能打上,有bug时用|,没有用&
{
int v = x | Next[0][i];//求并集
v &= Next[1][i];//求交集
if (d[v]>d[x] + t[i])
{
d[v] = d[x] + t[i];
q.push(P(d[v], v));
}
}
}
}
int main()
{
//freopen("t.txt", "r", stdin);
int n, m;
int rnd = 0;
char b1[N], b2[N];
while (~scanf("%d%d", &n, &m)&& (m || n))
{
for (int i = 0; i < m; i++)
{
scanf("%d %s %s", t + i, b1, b2);
pre[0][i] = pre[1][i] = Next[0][i] = Next[1][i] = 0;
for (int j = 0; j < n; j++)
{
if (b1[j] == '+')pre[0][i] |= (1 << j);//pre[0]存放必须有的bug的集合
if (b1[j] != '-')pre[1][i] |= (1 << j);//pre[1]存放任意状态的bug的集合,同理Next数组
if (b2[j] == '+')Next[0][i] |= (1 << j);
if (b2[j] != '-')Next[1][i] |= (1 << j);
}
}
dijkstra(n, m);
printf("Product %d\n", ++rnd);
if (d[0] == INF)
puts("Bugs cannot be fixed.");
else printf("Fastest sequence takes %d seconds.\n", d[0]);
puts("");
}
return 0;
}