(区间dp)2017icpc北京 Pangu and Stones

2017icpc北京 Pangu and Stones

题意&思路:

给n个石头,每次只能合并连续的l~r块,合并的代价是每堆石子的权值和,问最小的代价是多少。
看起来就是石子合并的进阶版(实际上也是),但是好难好难好难啊。看题解都看不懂,要感谢学长的讲解
记一下不太懂得部分:
dp[i][j][k]是i~j区间划分为k堆得代价,如果l≤k≤r得话,就可以组成一堆,代价就是i~j所有石子得权值和。p就是在i~j中得一点,划分区间。
dp[i][i][1]=0,dp[i][j][len]=0,石子自己一堆是初始状态,不需要代价;i~j的石子本身就是len堆,所以也不需要代价。
为什么dp这么难

代码:

#include<bits/stdc++.h>
#define pii pair<int,int>
#define ll long long
const int N=1e6+10;
const int mod=1e7+9;
const int maxn=0x3f3f3f3f;
const int minn=0xc0c0c0c0;
const int inf=99999999;
using namespace std;
int a[110],dp[110][110][110],sum[110]={0};
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int n,l,r,len,i,j,k,p;
	while(cin>>n>>l>>r)
	{
		for(i=1;i<=n;i++)
		{
			cin>>a[i];
			sum[i]=sum[i-1]+a[i];
		}
		memset(dp,maxn,sizeof(dp));
		for(i=1;i<=n;i++)
			dp[i][i][1]=0;
		for(len=1;len<=n;len++)
		{
			for(i=1;i<=n-len+1;i++)
			{
				j=i+len-1;
				//dp[i][j][len]=0;
				for(k=2;k<=len;k++)
				{
					for(p=i;p<=j;p++)
						dp[i][j][k]=min(dp[i][j][k],dp[i][p][1]+dp[p+1][j][k-1]);
					if(k>=l && k<=r)	
						dp[i][j][1]=min(dp[i][j][1],dp[i][j][k]+sum[j]-sum[i-1]);
				}
			}
		}
		if(dp[1][n][1]>=maxn)	dp[1][n][1]=0;
		cout<<dp[1][n][1]<<endl;
	}
	
	return 0;
}

发布了78 篇原创文章 · 获赞 0 · 访问量 1407

猜你喜欢

转载自blog.csdn.net/Z7784562/article/details/103904741