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;}