状压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是随便取的,取不存在的即可
View Code

 

以上是关于状压DP题集的主要内容,如果未能解决你的问题,请参考以下文章

POJ 3254 Corn Fields(状压DP)

动态规划---状压dp2

fzu2188 状压dp

状压DP(超详细!!!)

第一次接触状压DP

POJ 2411Mondriaan's Dream(状压dp)