洛谷T31039 九尾狐吃棉花糖

小夥伴出的題。html

一眼看出是狀壓DP裸題。回憶poj2288 islands and bridges,而後就很好寫了。ide

啪啪啪打了個狀壓DP出來(晚上寢室寫的,實際上是記憶化搜索),發現sum老是INF函數

而後發現:printf函數調用的貌似不是運行solve以後的,而是還未運行solve時的值。spa

因而分開寫就A了。code

出題者跑了一秒多,貌似用的二分...反正不怎麼看得懂。htm

果真DP大法吼哇!blog

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 typedef long long LL;
 5 using std::max;
 6 using std::min;
 7 const int N = 17;
 8 LL INF;
 9 int n;
10 
11 LL f[1 << N][N], sum[1 << N][N], G[N][N];
12 
13 void cal(int sta) {
14     int t[N];
15     for(int i = 0; i < n; i++) {
16         t[i] = (sta >> i) & 1;
17     }
18     for(int i = n - 1; i >= 0; i--) {
19         printf("%d", t[i]);
20     }
21     return;
22 }
23 
24 LL solve(int i, int j) {
25 
26     if(f[i][j] != INF) {
27         //printf("solve: ");
28         //cal(i);
29         //printf(" %d ans = %lld sum = %lld \n", j, f[i][j], sum[i][j]);
30         return f[i][j];
31     }
32 
33     int ct = 0;
34     for(int ii = 0; ii < n; ii++) {
35         ct += (i >> ii) & 1;
36     }
37     if(ct < 2) {
38         f[i][j] = INF - 1;
39         return INF - 1;
40     }
41 
42     LL ans = INF - 1, len = INF - 1;
43     int sta = ((~(1 << j)) & i);
44     for(int ii = 0; ii < n; ii++) {
45         if(!(G[ii][j] && ((i >> ii) & 1))) {
46             continue;
47         }
48         LL t_ans = max(solve(sta, ii), G[ii][j]);
49         LL t_len = sum[sta][ii] + G[ii][j];
50         if(t_ans < ans) {
51             ans = t_ans;
52             len = t_len;
53         }
54         else if(ans == t_ans) {
55             len = min(len, t_len);
56         }
57     }
58     f[i][j] = ans;
59     sum[i][j] = len;
60     //printf("solve: ");
61     //cal(i);
62     //printf(" %d ans = %lld sum = %lld \n", j, ans, len);
63     return ans;
64 }
65 
66 int main() {
67     memset(f, 0x7f, sizeof(f));
68     memset(sum, 0x7f, sizeof(sum));
69     INF = sum[1][1];
70 
71     int m, x, y;
72     LL R, z;
73     scanf("%d%d%lld", &n, &m, &R);
74     for(int i = 1; i <= m; i++) {
75         scanf("%d%d%lld", &x, &y, &z);
76         x--; y--;
77         if(x == y || z > R) continue;
78         if(G[x][y]) z = min(z, G[x][y]);
79         G[x][y] = G[y][x] = z;
80     }
81     for(int i = 1; i < n; i++) {
82         if(G[0][i]) {
83             int sta = 1 | (1 << i);
84             f[sta][i] = G[0][i];
85             sum[sta][i] = G[0][i];
86         }
87     }
88     int ed = (1 << n) - 1;
89     LL ans = solve(ed, (n - 1));
90     LL len = sum[ed][n - 1];
91     if(ans >= INF - 1) {
92         printf("wuwuwu~");
93     }
94     else {
95         printf("%lld %lld", ans, len);
96     }
97     return 0;
98 }
AC代碼
相關文章
相關標籤/搜索