题目大意:
给你N个食物,对应只能吃M个食物,有K个相对关系。
吃了对应的食物都会有对应的满意值,对应K个关系:
xi,yi,ci表示吃完xi马上吃yi能够额外获得ci的满意值。
问怎样吃能够获得最大满意值。
思路:
1、观察到NM都是18以内的数据,那么考虑状压dp:
①设定dp【i】【j】表示对应已经吃了状态J的食物,并且吃的最后一个食物的编号是i的最大满意值。假设j==5,5=101,其表示吃了第一个和第三个食物,没有吃第二个食物。
②那么我们不难推出其状态转移方程:
dp【i】【j】=max(dp【i】【j】,dp【k】【q】+a【i】+map【k】【i】);
这里j是当前状态,q是上一状态,那么q==j-(1<<i);表示吃完了k这个食物之后 ,然后紧接着吃食物i的状态转移。
其中map【k】【i】表示吃完k马上吃i能够获得的额外的满意值。
2、注意数组的初始化即可(好水的一个D)。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define ll __int64
ll dp[18][(1<<18)+15];
ll a[20];
ll map[20][20];
int main()
{
int n,m,k;
while(~scanf("%d%d%d",&n,&m,&k))
{
memset(dp,0,sizeof(dp));
memset(map,0,sizeof(map));
for(int i=0;i<n;i++)
{
scanf("%I64d",&a[i]);
}
while(k--)
{
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
x--;y--;
map[x][y]=w;
}
ll output=0;
for(int j=0;j<(1<<n);j++)
{
int cont=0;
ll tmp=j;
while(tmp)
{
if(tmp%2==1)cont++;
tmp/=2;
}
for(int i=0;i<n;i++)
{
if((j&(1<<i))!=0)
{
for(int k=0;k<n;k++)
{
if((j&(1<<k))!=0)
{
int q=j-(1<<i);
dp[i][j]=max(dp[i][j],dp[k][q]+a[i]+map[k][i]);
}
}
}
if(cont==m)output=max(output,dp[i][j]);
}
}
printf("%I64d\n",output);
}
}