石子合并-环形进化版
这次要说的题目是石子合并的升级版,对于线性,合并方法有规章可循,但是没有边缘的时候又应该怎么下手呢?
其实实现了之后理解深了固然会发现,其实核心思想是和上面一样的,但是要打破边际的限制,即1到n号石碓,n号之后接着是1号,
所以我们不宜再用之前的转移方程,我们新设定:
dp[ i ] [ j ]表示从i号石碓开始的j堆石子的最优合并情况,这样子就不用原来的设法解不出来了,对应转移方程如下:
dp[ i ][ j ]=min(dp[ i ][ j ],dp[ i ][ k ]+dp[ (i+k-1)%n+1 ][ j - k ]+sum(i,j))
取模就是n后面接着1,要重新从头取得意思。
代码如下:
#include<stdio.h> #include<iostream> using namespace std; int n,w[205],dp[205][205]; int min(int a,int b) { if(a>b) return b; return a; } int sum(int i,int t){//预处理 int k,s=0,k1; for(k=i;k<i+t;k++){ k1=k%n; if(k1==0) k1=n; s=s+w[k1]; } return s; } int main(){ int i,t,k; scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%d",&w[i]); dp[i][1]=0;//还没合并,不需花费 } for(t=2;t<=n;t++){ for(i=1;i<=n;i++){ dp[i][t]=0x3f3f3f3f; for(k=1;k<t;k++) dp[i][t]=min(dp[i][t],dp[i][k]+dp[(i+k-1)%n+1][t-k]+sum(i,t)); } } int minn=0x3f3f3f3f; for(i=1;i<=n;i++) minn=min(minn,dp[i][n]); printf("%d ",minn); }