早期DIV2场的一道D题,为了扫盲做的状压
题目很简单,把吃菜的情况状压一下,然后多记一维上一道菜吃了什么即可
转移方程:
dp[i][j][k]表示吃第i道菜,上一道吃的j,吃了的状态是k时的最大满足
dp[i][j][k|(1<<(t-1)]=max(dp[i][j][k|(1<<(t-1)],dp[i-1][j][k]+a[t]+G[t][j]);
注意这道题的空间会爆,所以把第一维滚动掉
下附代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define ll long long 5 using namespace std; 6 ll dp[2][20][262145]; 7 ll G[20][20]; 8 ll a[20]; 9 ll n,m,k; 10 int main(){ 11 memset(dp,-1,sizeof(dp)); 12 memset(G,0,sizeof(G)); 13 scanf("%lld%lld%lld",&n,&m,&k); 14 for (int i=1; i<=n; i++) 15 scanf("%lld",&a[i]); 16 for (int i=1; i<=k; i++){ 17 ll a,b,c; 18 scanf("%lld%lld%lld",&a,&b,&c); 19 G[a][b]=c; 20 } 21 for (int i=1; i<=n; i++){ 22 dp[1][i][1<<(i-1)]=a[i]; 23 } 24 int flag=1; 25 for (int i=2; i<=m; i++){ 26 flag=flag^1; 27 for (int j=1; j<=n; j++){ 28 for (int k=1; k<=n; k++){ 29 if (k!=j){ 30 for (int t=0; t<(1<<n); t++){ 31 if (t&(1<<(k-1)) && dp[flag^1][k][t]!=-1 && (t&(1<<(j-1)))==0){ 32 dp[flag][j][t|(1<<(j-1))]=max(dp[flag][j][t|(1<<(j-1))],dp[flag^1][k][t]+a[j]+G[j][k]); 33 } 34 } 35 } 36 } 37 } 38 } 39 ll res=0; 40 for (int i=1; i<=n; i++){ 41 for (int j=0; j<(1<<n); j++) 42 res=max(res,dp[flag][i][j]); 43 } 44 printf("%lld",res); 45 }