hdu4283 We Are The One

#校赛后的第一篇题解

#ac后评价:

        确实是区间dp的一道好题捏~

        但是本题题解属实不多,且区间dp题目一如既往的较难理解(本人看原有代码属实是一点没看懂),写一篇题解讲一下我做此题的(正经)方法。

#题目描述及翻译:

传送门:

Problem - 4283 (hdu.edu.cn)icon-default.png?t=N7T8https://acm.hdu.edu.cn/showproblem.php?pid=4283翻译:

        有一列男孩,每个男孩有一个diaosi值 di(代码里面被用作lis i)当一个男孩第k位上台时,unhappiness值为k*(di),有一个小黑屋,可以将男孩放入来调整位置,小黑屋满足栈的特性(FILO),求可能的最小unhappiness值之和。

#题目解答:

此题可以通过小区间的结果推出大区间的结果,显然是使用区间dp,既然使用区间dp,核心就是转移方程。

设dp数组为dp[ i ][ j ]: 含义是以i开头, j 结尾的区间 unhappiness值的最小值。

首先先for循环枚举区间长度len(区间dp都这么写),之后枚举i(即为开头),结尾j = i + len

dp[i][j]的状态转移请看下图(实际是懒得写了

(那个长得像u的东西是k,不要搞错了)

#ac代码

#include<bits/stdc++.h>
using namespace std;
const int INF = 998244353;
int T;
int main()
{
    cin>>T;
    int cas = 1;
    int dp[105][105];
    int lis[105];
    int sum[105];
    while(T--)
    {
        int n;
        cin>>n;
        memset(lis,0,sizeof(lis));
        memset(sum,0,sizeof(sum));
        memset(dp,0,sizeof(dp));
        for(int i = 1; i <= n; i++)
        {
            cin>>lis[i];
            sum[i] = lis[i] + sum[i-1];
        }
        for(int i = 1; i <= n; i++)
        {
            for(int j = i+1; j <= n; j++)
            {
                dp[i][j] = INF;
            }
        }
        for(int len = 1; len < n; len++)
        {
            for(int i = 1; i+len <= n; i++)
            {
                int j = i+len;
                for(int k = i; k <= j; k++)
                {
                    dp[i][j] = min(dp[i][j], dp[i+1][k] + dp[k+1][j] + (k-i)*lis[i] + (k-i+1)*(sum[j]-sum[k]));
                }
            }
        }
        cout<<"Case #"<<cas<<": "<<dp[1][n]<<endl;
        cas++;
    }
    return 0;
}

完结撒花~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值