10604 - Chemical Reaction解题报告
来源:互联网 发布:php gb2312转utf8 编辑:程序博客网 时间:2024/06/15 19:06
//这道题就只有我用的状态DP么?//DP时取当前的试剂组合,得出它们组成各种试剂的最小热量,以组合为状态就好#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 7, inf = 0x7f7f7f7f;struct Edge{ int a, b, emit, nxt;}edge[N * N];int head[N], n, m, e;int chemical[12];int F[1100][N];char dummy[N];void addedge(int a, int b, int c, int emit){ edge[e].a = a, edge[e].b = b, edge[e].emit = emit; edge[e].nxt = head[c]; head[c] = e++;}bool singlebit(int state){ while (!(state & 1)) state >>= 1; return state == 1;}int bitmatch(int state, int c){ int pos = 0; while (!(state & 1)) { state >>= 1; pos++; } return chemical[pos] == c;}int Dp(int state, int c){ int &ans = F[state][c]; if (ans != -1) return ans; if (singlebit(state)) return ans = bitmatch(state, c) ? 0 : inf; ans = inf; for (int i = 1, tmp1, tmp2; i != state; ++i) if ((i & state) == i) for (int cur = head[c]; cur != -1; cur = edge[cur].nxt) if ((tmp1 = Dp(state - i, edge[cur].b)) != inf && (tmp2 = Dp(i, edge[cur].a)) != inf) ans = min(ans, tmp1 + tmp2 + edge[cur].emit); return ans;}int main(){ #ifdef LOCAL freopen("in", "r", stdin); #endif // LOCAL int T; for (scanf("%d", &T); T--; ) { memset(head, -1, sizeof(head)); e = 0; scanf("%d", &m); for (int i = 1; i <= m; ++i) { for (int j = 1, c, emit; j <= m; ++j) { scanf("%d%d", &c, &emit); addedge(i, j, c, emit); } } scanf("%d", &n); for (int i = 0; i != n; ++i) scanf("%d", &chemical[i]); memset(F, -1, sizeof(F)); int ans = inf, state = (1 << n) - 1; for (int i = 1; i <= m; ++i) ans = min(ans, Dp(state, i)); printf("%d\n", ans); scanf("%s", dummy); } return 0;}