War2

题目背景

XM大战如期而至,Agent们齐聚一地,展开最后的对决。对战有很多种方式,有些复杂的方式可以获得更高的分数。可惜ENLIGHTENED的人并不怎么聪明,只会简单的hack,所以ENLIGHTENED行动指挥找到了你来做他们的总参谋。

题目描述

地图上有NN个Portal,现在某一名Agent的任务是占领该地图上的MM个Portal,这名Agent占领第ii个Portal可以得到的分数为A[i]A[i],除了直接占领,还有其他的KK种加分方式,对于着NN个Portal,在占领完第X[i]X[i]个Portal后占领第Y[i]Y[i]个Portal可以获得B[i]B[i]的加分,加分可能会有重复。Agent希望他可以为团队争取更多的分数,所以请求作为大战参谋的你来帮助他。

输入输出格式

输入格式:

 

第一行是输入三个整数N,M,KN,M,K 第二行输入是NN个数,第ii个数代表A[i]A[i]的值。 下面KK行每行有3个整数X[i],Y[i],C[i]X[i],Y[i],C[i],表示在占领完第X[i]X[i]个Portal后占领第Y[i]Y[i]个Portal可以获得B[i]B[i]的加分

 

输出格式:

 

输出仅一行一个整数,为该名Agent可以获得的最大分数值。

 

输入输出样例

输入样例#1: 复制

3 2 1
1 1 1
1 2 3

输出样例#1: 复制

5

输入样例#2: 复制

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

输出样例#2: 复制

6

说明

对于20\%20%的数据 1 \leq M \leq N \leq 4,0 \leq A[i],B[i] \leq 10^31≤M≤N≤4,0≤A[i],B[i]≤103

对于40\%40%的数据 1 \leq M \leq N \leq 8,0 \leq A[i],B[i] \leq 10^51≤M≤N≤8,0≤A[i],B[i]≤105

对于60\%60%的数据 1 \leq M \leq N \leq 12,0 \leq A[i],B[i] \leq 10^71≤M≤N≤12,0≤A[i],B[i]≤107

对于100\%100%的数据 $1 \leq M,X[i],Y[i] \leq N \leq 18,0 \leq K \leq N^2−N,0 \leq A[i],B[i] \leq 10^9$

 

我们DP数组f[i][j],i用状态压缩,代表有那些点已经被占领过了,j代表上一次我占的是那个。对于每一次状态转移,若当前我们要占领的Portal在占领j后有加分,那么就转移加分与基础值的和,否则只转移基础值。最后判断一下当i代表的状态已经有占领m个了,就记录下当前的最大值。

#include<bits/stdc++.h>
#define f(i,l,r) for(i=(l);i<=(r);i++)
using namespace std;
const int MAXN=19;
int n,m,K;
long long ans;
long long f[1<<19][MAXN],a[MAXN],b[MAXN][MAXN];
int main()
{
	ios::sync_with_stdio(false);
	int i,j,k,x,y,w,num=0;
	cin>>n>>m>>K;
	f(i,0,n-1){
		cin>>a[i];
	}
	f(i,1,K){
		cin>>x>>y>>w;
		if(x==y) a[i]+=w;
		else b[x-1][y-1]+=w;
	}
	f(i,0,n-1){
		f[1<<i][i]=a[i];
	}
	f(i,1,(1<<n)-1){
		num=0;
		f(j,0,n-1){
			if(!(i&(1<<j))) continue;
			num++;
			f(k,0,n-1){
				if(!(i&(1<<k))) continue;
				if(k==j) continue;
				f[i][j]=max(f[i][j],f[i^(1<<j)][k]+a[j]+b[k][j]);
			}
		}
		if(num==m){
			f(j,0,n-1){
				if(!(i&(1<<j))) continue;
				ans=max(ans,f[i][j]);
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值