题目大意:给出n和m,有n种化学药剂,型号由1~n,然后给出n * n行代表相应的两种化学药剂反应后的生成物以及释放的热量,然后给出m个试管,每种试管中有对应的药剂,要求将m种药剂反应合成一种,不要求反应后药剂的种类,要求反应所散发的热量最少。
注意:i和j反应可能与j和i反应不同,反应可能吸热,每组测试以/结束。
解题思路:开一个cnt数组记录每种药剂的数量,然后用递归的方法遍历所有的情况,并且要记录相同的子情况。
#include <cstdio> #include <cmath> #include <cstring> #include <climits> using namespace std; int m, k, DP[2000010], A[8][8][2]; int DPS(int x) { if (DP[x] != -1) return DP[x]; DP[x] = INT_MAX; for (int i = 0; i < m; i++) { for (int j = 0; j < m; j++) { if (x / ((int)pow(11.0, i)) % 11 == 0 || x / ((int)pow(11.0, j)) % 11 == 0) continue; if (i == j && x / ((int)pow(11.0, i)) % 11 < 2) continue; if (DP[x] > DPS(x - pow(11.0, i) - pow(11.0, j) + pow(11.0, A[i][j][0]-1)) + A[i][j][1]) DP[x] = DPS(x - pow(11.0, i) - pow(11.0, j) + pow(11.0, A[i][j][0]-1)) + A[i][j][1]; } } return DP[x]; } int main() { int T; scanf("%d", &T); while (T--) { memset(DP, -1, sizeof(DP)); scanf("%d", &m); for (int i = 0; i < m; i++) for (int j = 0; j < m; j++) scanf("%d%d", &A[i][j][0], &A[i][j][1]); scanf("%d", &k); int dst = 0; for (int i = 0; i < k; i++) { int temp; scanf("%d", &temp); dst = dst + pow(11.0, temp - 1); } for (int i = 0; i < m; i++) for (int j = 0; j < 11; j++) DP[(int)(pow(11.0,i)*j)] = 0; printf("%d\n", DPS(dst)); scanf("%*s"); } return 0; }