状压DP题集
Posted 00isok
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了状压DP题集相关的知识,希望对你有一定的参考价值。
【状压DP】Codeforces - 580D Kefa and Dishes (状压DP+记忆化搜索)(经典)
题目大意:
有$n ( n \leq18 )$个菜,现在要挑选$m$道菜,每个菜有一个满意度$a_i$,还有$k$个关系,每个关系为 $a b c$,表示$a$在$b$之前吃的话,就会额外增加$c$的满意度,现在要你输出最大的满意度。
解题分析:
$n$的数据范围很小,很容易想到状压DP。
#include <bits/stdc++.h> using namespace std; #define REP(i,s,t) for(int i=s;i<=t;i++) typedef long long ll; int n,m,k; ll a[25],dp[(1<<20)][25],mp[25][25]; //dp[i][j]表示上一个选的是j,然后选了i中二进制表示的所有物品之后所取得的最大价值 ll DP(int cur,int last) if(__builtin_popcount(cur)==m)return 0; //判断是否已经选够m件物品 if(dp[cur][last]!=-1)return dp[cur][last]; ll ans=0; REP(i,0,n) if(cur&(1<<i))continue; //选过这个数就跳过 ans=max(ans,a[i]+mp[last][i]+DP(cur|(1<<i),i)); return dp[cur][last]=ans; int main() scanf("%d%d%d",&n,&m,&k); REP(i,0,n-1)scanf("%lld",&a[i]); while(k--) int a,b,c;scanf("%d%d%d",&a,&b,&c); mp[--a][--b]=c; memset(dp,-1,sizeof(dp)); printf("%lld\n",DP(0,20)); //20是随便取的,取不存在的即可
以上是关于状压DP题集的主要内容,如果未能解决你的问题,请参考以下文章