hdu 4283

n个人,每个人第i个选中时会产生一个值,为d[k] * (i-1),问全部选这n个人的最小的值。
区间dp,d[i][j]表示[i,j]里面的产生的最小的值,计算d[i][j]时可知[i,j]有j-i+1个人,可以枚举第i个人(区间最左边的人)是第第几个被选的。若是第k个被选中,则转化为两个子问题d[i+1][i+k-1],d[i+k][j],这一步产生的值为d[i] * (k-1 ) + (sum[j] - sum[i+k-1] )*k;
记忆化大法好

#include <cstring>
#include <algorithm>

using namespace std;
int t,n,a[110],cas,d[110][110],sum[110];
int dp(int i,int j){
	int & ans = d[i][j];
	if(ans != 1e9) return ans;
	if(i >= j ) return ans = 0;
	for(int k = 1;k<=j-i+1;k++)	{
		ans = min(ans,dp(i+1,i+k-1)+dp(i+k,j)+a[i]*(k-1)+(sum[j]-sum[i+k-1])*k);
	}
	return ans;
} 

int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for(int i = 0;i<101;i++)for(int j = 0;j<101;j++) d[i][j] = 1e9;
		memset(sum,0,sizeof(sum));
		for(int i = 1;i<=n;i++){	
			scanf("%d",a+i);
			sum[i] = sum[i-1] + a[i]; 	
		} 
		printf("Case #%d: %d\n",++cas,dp(1,n));
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/winhcc/article/details/88823397