• UVa 10604 Chemical Reaction(hash记忆化搜索)


    题意:

    每组数据开始有一个整数n,表示有n种试剂(最多6种)。接下来的n*n行列出来了每种试剂混合产生的化合物以及放出的热量。
    然后一个整数m,代表有m个试管(最多10个)。
    接下来一行有m个数,表示m个试管里分别装了哪几种试剂。

    问怎么组合能产生最少的热量。测试样例之间用/分开,结果用.表示

    思路:

    http://www.cnblogs.com/staginner/archive/2011/12/06/2277838.html

    主要是定义了一个hash,由于每一个状态只能用一个数组来表示,所以给每个状态都生成一个hash值,然后记忆化搜索

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <climits>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 10;
    const int MAXD = 50000;
    const int HASH = 1000003;
    int f[MAXD];
    int g[MAXN][MAXN], heat[MAXN][MAXN];
    int head[HASH], next[MAXD], e;
    int st[MAXD][6];
    int N, K;
    
    int hash(int p[])
    {
        int v = 0;
        for (int i = 0; i < 6; ++i)
            v = v * 10 + p[i];
        return (v & 0x7fffffff) % HASH;
    }
    
    void insert(int s)
    {
        int h = hash(st[s]);
        next[e] = head[h];
        head[h] = e++;
    }
    
    int check(int s)
    {
        int i, h = hash(st[s]);
        for (i = head[h]; i != -1; i = next[i])
            if (memcmp(st[i], st[s], sizeof(st[0])) == 0)
                break;
        return i;
    }
    
    int dp(int u)
    {
        int k = check(u);
        if (k >= 0)
            return f[k];
    
        insert(u);
    
        int mm = INT_MAX;
        for (int i = 0; i < 6; ++i)
        {
            if (st[u][i])
                for (int j = 0; j < 6; ++j)
                    if (st[u][j])
                    {
                        if (i == j && st[u][j] < 2)
                            continue;
                        memcpy(st[e], st[u], sizeof(st[e]));
                        --st[e][i], --st[e][j], ++st[e][g[i][j]];
                        mm = min(mm, dp(e) + heat[i][j]);
                    }
        }
        if (mm == INT_MAX)
            mm = 0;
        return f[u] = mm;
    }
    
    int main()
    {
        int cases;
        scanf("%d", &cases);
        while (cases--)
        {
            scanf("%d", &N);
    
            for (int i = 0; i < N; ++i)
                for (int j = 0; j < N; ++j)
                {
                    int a, b;
                    scanf("%d %d", &a, &b);
                    g[i][j] = --a;
                    heat[i][j] = b;
                }
    
            memset(head, -1, sizeof(head));
            memset(st[0], 0, sizeof(st[0]));
            scanf("%d", &K);
            for (int i = 0; i < K; ++i)
            {
                int a;
                scanf("%d", &a);
                ++st[0][--a];
            }
            e = 0;
            printf("%d\n", dp(e));
    
            char b[10];
            scanf("%s", b);
        }
        return 0;
    }

     

    -------------------------------------------------------

    kedebug

    Department of Computer Science and Engineering,

    Shanghai Jiao Tong University

    E-mail: kedebug0@gmail.com

    GitHub: http://github.com/kedebug

    -------------------------------------------------------

  • 相关阅读:
    Windows 10 win 10 切换输入法的快捷键
    windows 7输入regedit 打不开注册表
    ios开发之NSData
    ios数组倒序
    iOS NSString使用stringWithFormat的拼接
    BLE 广播格式定义
    低功耗蓝牙UUID三种格式转换
    iOS 如何判断一个点在某个指定区域中
    iOS 毛玻璃效果的实现方法
    iOS毛玻璃效果的实现方法
  • 原文地址:https://www.cnblogs.com/kedebug/p/2787556.html
Copyright © 2020-2023  润新知