[jzoj 4255] ACM {DP+优化}

版权声明:请大家斧正,如喜欢的话,为拙见点一个赞吧。 https://blog.csdn.net/qq_39897867/article/details/86729931

题目

Description
Zagreb大学的ACM队伍(由三个人组成)正在打Final。他们的技术指导提出了一个牛逼的策略如下。
在一开始,队伍的每一个人会评估每一道题的难度,难度会用1~5的整数表示,数字越大题目越难。然后他们会分配题目给每个人。题目会分成三个部分,每个队员会拿到一个非空的连续的题目代表了他要解决的问题。他们的策略是让难度评估系数最小。难度评估系数是三个队员对各自所拿到题目的难度评估的总和。你的任务是计算这个最小的难度评估系数。

Input
第一行包括了一个整数N(3<=N<=150000),代表题目数量。
接下来的三行,每行N个1~5的整数,每一行代表一个队员对N道题的难度评估。

Output
输出一个整数。代表最小的难度评估系数。


结题思路

比赛时打了一个WA的暴力。 对于正解:

  1. O ( n 2 ) D P O(n^2)DP +斜率优化(这种东西不存在的
  2. O ( n ) D P O(n)DP

f [ i ] [ j ] f[i][j] 表示目前是第i个人第j件物品时的最小难度评估系数。
动态转移方程为: f [ i ] [ j ] = m i n ( f [ i ] [ j 1 ] , f [ i 1 ] [ j 1 ] ) + a [ i ] [ j ] f[i][j]=min(f[i][j-1],f[i-1][j-1])+a[i][j]

注意常数


代码

#include<cstdio>
#include<algorithm>
#include<cstring>
#define fre(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout)
#define rep(i,x,y) for(register int i=x;i<=y;i++)
using namespace std;
int n,f[4][150001],ans=0x3f3f3f3f,a[4][150001]; 
void aa(){swap(a[2],a[3]);}
void bb(){swap(a[1],a[2]);}
void dp(){
	memset(f,0x3f3f3f3f,sizeof(f)); f[0][0]=0; 
	rep(i,1,3) rep(j,1,n) f[i][j]=min(f[i][j-1],f[i-1][j-1])+a[i][j]; 
	ans=min(ans,f[3][n]); 
}
int main(){
//	fre(acm); 
	scanf("%d",&n); 
	rep(i,1,3) rep(j,1,n) scanf("%d",&a[i][j]);
	dp(); aa(); dp(); bb(); dp(); aa(); dp(); bb(); dp(); aa(); dp();
	printf("%d",ans); 
}

猜你喜欢

转载自blog.csdn.net/qq_39897867/article/details/86729931
今日推荐