CF580 D. Kefa and Dishes (状压DP)

传送门

题意
n n n个食物中选择 m m m个,使得获得的满意度最大。先吃 a a a食物再吃 b b b食物可以获得额外的满意度。
问最后你能获得的最大满意度是多少。
思路
d p [ s ] [ j ] dp[s][j] dp[s][j]表示在状态 s s s下,最后吃的是食物 j j j获得的最大满意度。
转移方程
d p [ s ] [ j ] = m a x ( d p [ s ∣ ( 1 &lt; &lt; j ) ] [ i ] + m p [ i ] [ j ] + w [ j ] ) dp[s][j]=max(dp[s|(1&lt;&lt;j)][i]+mp[i][j]+w[j]) dp[s][j]=max(dp[s(1<<j)][i]+mp[i][j]+w[j])
表示的是从先吃了食物 i i i,还没吃食物 j j j的状态转移到最后吃了食物 j j j的状态。
注意一下还要用个变量纪录吃了多少个食物。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6+5;
const int N = 27;
const int mod = 19930726;

int n,m,k;
int mp[N][N],w[N];
ll dp[1<<18|5][19];
int main(){
	scanf("%d%d%d",&n,&m,&k);
	for(int i = 0; i < n; i++){
		scanf("%d",&w[i]);
	}
	for(int i = 1; i <= k; i++){
		int a,b;
		scanf("%d%d",&a,&b);
		scanf("%d",&mp[a][b]);
	}
	int sz = 1<<n;
	ll ans = 0;
	for(int s = 0; s < sz; s++){
		int cnt = 0;
		for(int i = 0; i < n; i++){
			if(s&(1<<i)){
				cnt++;
				for(int j = 0; j < n; j++){
					if(s&(1<<j))
						dp[s][j] = max(dp[s][j],dp[s^(1<<j)][i]+mp[i+1][j+1]+w[j]);
				}
			}
		}
		if(cnt == m) 
			for(int j = 0; j < n; j++) ans = max(ans,dp[s][j]);
	}
	printf("%lld\n",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值