题目链接:http://codeforces.com/contest/580
题意:给出n种菜只能选m样。而且不能重复,而且如果按照某种规则来选菜的话还有额外的加成。
规则就是严格在某样菜的上一个选指定的菜。最后问最大权值为多少。
题解:看数据n,m最大18化作二进制也就不超过2^18 = 262 144,所以可以考虑用一下状压dp,
dp[i][j],i表示状态,j表示当前选择的是那样菜。
#include <iostream> #include <cstring> #include <cstdio> using namespace std; typedef long long ll; const int M = (1 << 18); int a[20] , ve[20][20]; ll dp[M][19]; int main() { int n , m , k , u , v , w; scanf("%d%d%d" , &n , &m , &k); memset(ve , 0 , sizeof(ve)); for(int i = 0 ; i < n ; i++) { scanf("%d" , &a[i]); } for(int i = 0 ; i < k ; i++) { scanf("%d%d%d" , &u , &v , &w); ve[u - 1][v - 1] = w; } memset(dp , -1 , sizeof(dp)); for(int i = 0 ; i < n ; i++) { dp[(1 << i)][i] = (ll)a[i]; } ll MAX = 0; for(int i = 0 ; i < (1 << n) ; i++) { int count = 0; int gg = i; while(gg) { count += gg % 2; gg /= 2; } for(int j = 0 ; j < n ; j++) { if(dp[i][j] != -1) { if(count == m) { MAX = max(MAX , dp[i][j]); } for(int k = 0 ; k < n ; k++) { if(!(i & (1 << k))) { ll sum = 0; sum += (ll)ve[j][k]; sum += (ll)a[k]; dp[i | (1 << k)][k] = max(dp[i | (1 << k)][k] , dp[i][j] + sum); } } } } } printf("%I64d " , MAX); //cout << MAX << endl; return 0; }