洛谷T31039 九尾狐吃棉花糖

小伙伴出的题。

一眼看出是状压DP裸题。回忆poj2288 islands and bridges,然后就很好写了。

啪啪啪打了个状压DP出来(晚上寝室写的,其实是记忆化搜索),发现sum总是INF

然后发现:printf函数调用的貌似不是运行solve之后的,而是还未运行solve时的值。

于是分开写就A了。

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

果然DP大法吼哇!

 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代码

 

posted @ 2018-05-26 14:41  garage  阅读(134)  评论(0编辑  收藏  举报