【状压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是随便取的,取不存在的即可 }
原文地址:https://www.cnblogs.com/00isok/p/11184838.html
时间: 2024-10-06 13:09:47