NYOJ 737 (石子合并)

本文介绍了一种使用动态规划(DP)解决区间合并问题的方法。通过枚举所有子区间并寻找最大值来求解最优合并值。文章提供了完整的代码实现,并详细解释了状态转移方程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

该题是一道DP题,核心思想如下:

某个区间一定是这个区间内的某两个子区间合成的(这两个子区间互补,即这两个区间加起来等于大区间),

所以我们枚举所有的情况,取个最大值即可。因为最初是从2堆石子开始无法选择,到数量大了就可以择优,体现出DP的优势。

DP[ i ] [ j ]表示 i 到 j 区间的最优合并值。

则由上述思想转移方程如下:

dp[ i ][ j ] = min(  dp[ i ][ j ], dp[ i ][ k ] + dp[k + 1][ j ] + sum[ i ][ j ] ) (i <= k <= j - 1)。

#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
int n, s[205][205], a[205], f[205][205];

int main()
{
    while(scanf("%d", &n) != EOF)
    {
        memset(s, 0, sizeof s );
        memset(a, 0, sizeof a );
        memset(f, 0, sizeof f );
        for(int i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        for(int i = 1; i <= n; i++)
        {
            for(int j = i; j <= n; j++)
            {
                f[i][j] = 0x3f3f3f3f;//初值赋无限大 
                for(int k = i; k <= j; k++)
                    s[i][j] = s[i][j] + a[k];
            }
        }
        for(int i = 1; i <= n; i++)
            f[i][i] = 0;//自身初值为0 
        for(int i = 1; i < n; i++)
        {
            for(int j = 1; j <= n-i; j++)
            {
                for(int k = j; k <= i + j - 1; k++)
                {
                    if(f[j][i+j] > f[j][k] + f[k+1][i+j]+s[j][i+j])
                        f[j][i+j] = f[j][k] + f[k+1][i+j]+s[j][i+j];
                }
                printf("f[%d][%d] = %d\n", j, i+j, f[j][i+j]); 
            }
        }
        printf("%d\n", f[1][n]);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/fantastic123/p/8972831.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值