uva_10604 - Chemical Reaction( Hash+状态压缩 )

这个题一开始想用六维数组直接跑的,但是考虑到药物或者序列更多的话就不实际了,这里我是用了hash对状态压缩然后DP
hash: elfhash
状态: 就是序列, 对应不同的结果保存最小解然后递归记忆求解

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define MAXV    10
#define MAXC    11
#define MAXN    1000001
#define INF     0x7fffffff

typedef struct NODE_ {
        int heat;
        char mix_rst;
}NODE;

int  hash[MAXN], ans;
NODE tab[MAXV][MAXV];
char save[MAXN][MAXC], t[MAXC];

inline int elf_hash(char *str)
{
        unsigned long h( 0x0L ), x( 0x0L );
        strcpy(t, str); char *ptr = t;
        while( *ptr ) {
                h = (h<<4)+(*ptr ++);
                if( (x = h&0xF0000000L) ) {
                        h ^= (x>>24); h &= ~x;
                }
        }
        int idx( h%MAXN );
        while( (INF != hash[idx]) && strcmp(str, save[idx]) ) {
                idx = (idx+1)%MAXN;
        }
        strcpy(save[idx], str); return idx;
}

inline int mix_chemical(const char *str, const int &idx1, const int &idx2, char *des)
{
        int x, y, s, f, idx(0), flag(0);
        x = str[idx1]-'0'; y = str[idx2]-'0';
        s = min(idx1, idx2); f = max(idx1, idx2);
        des[idx ++] = tab[x][y].mix_rst;
        for(int i = 0; i < strlen(str); i ++) {
                if( i != idx1 && i != idx2 ) {
                        des[idx ++] = str[i];
                }
        }
        des[idx] = '\0'; return tab[x][y].heat;
}

int dfs(char *str)
{
        if( 2 > strlen(str) ) {
                return 0;
        }
        char tmp[MAXC];
        int idx( elf_hash(str) ), rst(INF), x, y;
        if( INF != hash[idx] ) {
                return hash[idx];
        }
        for(int i = 0; i < strlen(str); i ++) {
                for(int j = i+1; j < strlen(str); j ++) {
                        rst = min(rst, mix_chemical(str, i, j, tmp)+dfs(tmp));
                        rst = min(rst, mix_chemical(str, j, i, tmp)+dfs(tmp));
                }
        }
        return hash[idx] = rst;
}

int main(int argc, char const *argv[])
{
#ifndef ONLINE_JUDGE
        freopen("test.in", "r", stdin);
#endif
        int cas, n, m, v;
        char str[MAXC], ch[3];
        scanf("%d", &cas);
        for( ; cas; cas --) {
                scanf("%d", &n);
                for(int i = 1; i <= n; i ++) {
                        for(int j = 1; j <= n; j ++) {
                                scanf("%d %d", &v, &tab[i][j].heat); 
                                tab[i][j].mix_rst = v+'0';
                        }
                }
                scanf("%d", &m);
                for(int i = 0; i < m; i ++) {
                        scanf("%d", &v); str[i] = v+'0';
                }
                str[m] = '\0'; scanf("%s", ch); ans = INF;
                memset(save, '\0', sizeof(save));
                for(int i = 0; i < MAXN; i ++) {
                        hash[i] = INF;
                }
                printf("%d\n", dfs(str));
        }
        return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值