石子合并-环形进化版

这次要说的题目是石子合并的升级版,对于线性,合并方法有规章可循,但是没有边缘的时候又应该怎么下手呢?

其实实现了之后理解深了固然会发现,其实核心思想是和上面一样的,但是要打破边际的限制,即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); 

} 

 

posted @ 2018-05-02 02:07  fantastic123  阅读(165)  评论(0编辑  收藏  举报