题意:n件物品,第i件物品价值为a[i].现在要选m件物品.
有k个加成,若物品x正好在物品y的前一个 则总价值+a[x][y]
m<=n<=18,0<=a[i],c[x][y]<=1e9.问能选出的最大价值为?
暴力dfs O(C(n,m)*m!) TLE....
建图 (i->j)的边权值为(a[i]+c[i][j]).
现在就是找到一条长度为m-1并且权值最大的路径.
明显状压.设dp[s][u] 表示在u点,并且经过的点的状态为s.
dp[s][u] + a[j]+c[u][j] -> dp[s|2^j][j] (u在s并且j不再s)
有k个加成,若物品x正好在物品y的前一个 则总价值+a[x][y]
m<=n<=18,0<=a[i],c[x][y]<=1e9.问能选出的最大价值为?
暴力dfs O(C(n,m)*m!) TLE....
建图 (i->j)的边权值为(a[i]+c[i][j]).
现在就是找到一条长度为m-1并且权值最大的路径.
明显状压.设dp[s][u] 表示在u点,并且经过的点的状态为s.
dp[s][u] + a[j]+c[u][j] -> dp[s|2^j][j] (u在s并且j不再s)
res=max(res, dp[s][i] (i=1..n && bit(s)==m))
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=19;
int n,m,k;
ll a[N],b[N][N];
ll dp[1<<N][N];
int main()
{
cin>>n>>m>>k;
for(int i=0;i<n;i++)
cin>>a[i];
while(k--)
{
ll u,v,x;
cin>>u>>v>>x;
u--,v--;
b[u][v]=x;
}
for(int i=0;i<n;i++)
dp[1<<i][i]=a[i];
for(int i=0;i<(1<<n);i++)
{
for(int j=0;j<n;j++)
{
if(!((i>>j)&1))
continue;
for(int k=0;k<n;k++)
{
if((i>>k)&1)
continue;
dp[i|(1<<k)][k]=max(dp[i|(1<<k)][k],dp[i][j]+a[k]+b[j][k]);
}
}
}
ll res=0;
for(int i=0;i<(1<<n);i++)
{
int cnt=0;
for(int j=0;j<n;j++)
if((i>>j)&1)
cnt++;
if(cnt==m)
{
for(int j=0;j<n;j++)
{
if(i&(1<<j))
res=max(res,dp[i][j]);
}
}
}
cout<<res<<'\n';
return 0;
}