【动态规划】2018 ACM-ICPC EC final I

【动态规划】2018 ACM-ICPC EC final I

题目链接:https://ac.nowcoder.com/acm/contest/366/I
分析可以发现,后面的天数不会对前面产生影响,但前面的会对后面产生影响。且最后一天一定会进行攻击操作。考虑倒向进行DP。
dp[i][j][k]表示第i次及之后共进行了j次攻击操作,这些操作的次数和为k的时候的最大攻击效果。
如果进行操作1:
dp[i][j][k]=dp[i+1][j-1][k-i]+a[i]
如果进行操作2:
dp[i][j][k]=dp[i+1][j][k]+b[i](x1-i+x2-i+…+xj-i)(X为选取的攻击的轮数集合)
=dp[i+1][j][k]+b[i]
(k-ij)
如果进行操作3:
dp[i][j][k]=dp[i+1][j][k]+c[i]
[j]
三种操作取max,为了优化内存采用迭代数组。

#include<bits/stdc++.h>
using namespace std;
#define cur (i%2)
#define las (cur^1)
long long dp[2][102][5600];
int n,T;
long long a[102],b[102],c[102];
long long ans;


int main(){
	
	 scanf("%d",&T);
	 while(T){
	 	T--;
	 	scanf("%d",&n);
	 	for(int i=1;i<=n;i++){
	 		scanf("%lld%lld%lld",&a[i],&b[i],&c[i]);
		}
		memset(dp,0,sizeof(dp));
		dp[n%2][1][n]=a[n];
		ans=0;
		
		for(int i=n-1;i>=1;i--){
			memset(dp[cur],0,sizeof(dp[cur]));
			for(int j=1;j<=n-i+1;j++){

				for(int k=n+(i+i+j-2)*(j-1)/2;k<=(n+n-j+1)*j/2;k++){
				//	dp[cur][j+1][k+i]=max(dp[cur][j+1][k+i],dp[las][j][k]+a[i]);
					if(j>=2) dp[cur][j][k]=max(dp[cur][j][k],dp[las][j-1][k-i]+a[i]);
					if(j!=n-i+1) dp[cur][j][k]=max(dp[cur][j][k],dp[las][j][k]+max(c[i]*j,b[i]*(k-i*j)));
					if(i==1){
						ans=max(ans,dp[cur][j][k]);
					}
					//printf("dp[%d][%d][%d] = %lld\n",i,j,k,dp[cur][j][k]);
				}
				
			}
			
		}
		printf("%lld\n",ans);
	 }
	
	
	return 0;
} 
	
	return 0;
} 

你可能感兴趣的:(ACM)