题干:

kefa进入了一家餐厅,这家餐厅中有n个菜(0<n≤18),kefa对第i个菜的满意度为ai(0≤ai≤10^9),并且对于这n个菜有k个规则,如果kefa在吃完第xi个菜之后吃了第yi个菜(保证xi、yi不相等),那么会额外获得ci(0≤ci≤10^9)的满意度。kefa要吃m道任意的菜(0<m≤n),但是他希望自己吃菜的顺序得到的满意度最大,请你帮帮kefa吧! 
输入第一行是三个数:n,m,k 
第二行是n个数,第i个数表示kefa对第i道菜的满意度为ai 
第三行到第k+2行每行有3个数:xi,yi,ci,表示如果kefa在吃完第xi道菜之后立刻吃了第yi道菜,则会额外获得ci的满意度

Examples

Input

2 2 1
1 1
2 1 1

Output

3

Input

4 3 2
1 2 3 4
2 1 5
3 4 2

Output

12

Note

样例1中,按照2,1的顺序,可以额外获得1点满意度。 
样例2中,按4,2,1或者2,1,4,都可以额外获得5点满意度。

 

解题报告:

   dp[i][j],i代表已经吃过了哪些菜,j代表最后吃的是哪个菜,然后更新判断就好了。

AC代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll dp[1<<18][20];
ll a[20],val[20][20];
ll n,m,k;
bool ok(ll x) {
	int res = 0;
	for(ll i = 1; i<=(1<<n); i<<=1) {
		if(i & x) res++;
	}
	if(res == m) return 1;
	else return 0;
}
int main()
{
	ll u,v;
	scanf("%lld%lld%lld",&n,&m,&k);
	for(int i = 1; i<=n; i++) {
		scanf("%lld",a+i);
	}
	for(int i = 1; i<=k; i++) {
		scanf("%lld%lld",&u,&v);
		scanf("%lld",&val[u][v]);
	}
	memset(dp,-1,sizeof dp);
	for(int i = 1; i<=n; i++) {
		dp[(1<<i-1)][i] = a[i];
	}
	for(int bit = 0; bit<=(1<<n)-1; bit++) {
		for(int i = 1; i<=n; i++) {
			if(dp[bit][i] == -1) continue;
			for(int j = 1; j<=n; j++) {
				if(i != j && (bit&(1<<(j-1))) ==0) {
					dp[bit|(1<<(j-1))][j] = max(dp[bit][i] + a[j] + val[i][j],dp[bit|(1<<(j-1))][j]);
				}
			}
		}
	}
	ll maxx = 0;
	for(int bit = 0; bit<=(1<<n)-1; bit++) {
		if(ok(bit)) {
			for(int i = 1; i<=n; i++) {
				maxx = max(maxx,dp[bit][i]);
			}
		}
	}
	printf("%lld\n",maxx);
	return 0 ;
}

总结:还是太菜了、、、、and  这种东西位运算啥的包装成函数最好。