P4802 [CCO 2015]路短最

${\color{Cyan}{>>Question}}$

简单的状压$dp$,

P1171 售货员的难题简直一模一样(但也正因为此把我坑了)

令$f[i][j]$表示状态$i$,最后在$j$的最短路最长路(又坑了我)

有$$f[i][j] = max\left\{f[i-\left \{ j \right \}][k]+dis[k][j]\;\;|\;\;k\in (i-\left \{ j \right \})\right\}$$

!!要初始化为极小值!!(不初始化只有$46pts$)

!!边界!!$$f[i][0] = 0$$

枚举时可以只枚举奇数的状态(因为$0$号点必选)

上代码

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <cstring>
 5 #define ll long long
 6 using namespace std; 
 7 
 8 template <typename T> void in(T &x) {
 9     x = 0; T f = 1; char ch = getchar();
10     while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
11     while( isdigit(ch)) {x = 10 * x + ch - 48; ch = getchar();}
12     x *= f;
13 }
14 
15 template <typename T> void out(T x) {
16     if(x < 0) x = -x , putchar('-');
17     if(x > 9) out(x/10);
18     putchar(x%10 + 48);
19 }
20 //-------------------------------------------------------
21 
22 const int N = 20;
23 
24 int n,m;
25 int a[N][N];
26 int f[1<<N][N];
27 
28 int main() {
29     int i,j,k,u,v;
30     in(n); in(m);
31     for(i = 0;i < m; ++i) {
32         in(u); in(v); in(a[u][v]);
33     }
34     memset(f,~0x3f,sizeof(f));//debug 要赋极小值
35     f[1][0] = 0;//!边界! 
36     for(i = 3;i < (1<<n); i += 2) {
37         f[i][0] = 0;//!边界! 
38         for(j = 0;j < n; ++j) {
39             if(!(i&(1<<j))) continue;
40             for(k = 0;k < n; ++k) {
41                 if(!a[k][j] || !(i&(1<<k))) continue;
42                 f[i][j] = max(f[i][j],f[i^(1<<j)][k]+a[k][j]);
43             }
44         }
45     }
46     //out(f[(1<<n)-1][n-1]);//debug
47     int ans = 0;
48     for(i = 1|(1<<n-1);i < (1<<n); i += 2) ans = max(ans,f[i][n-1]);
49     out(ans);
50     return 0;
51 }

 

posted @ 2019-08-15 15:29  陈星卿  阅读(190)  评论(0编辑  收藏  举报