zoukankan      html  css  js  c++  java
  • HDU4283 You Are the One(经典区间dp)

    动态规划要从最优子结构来推出大的方案

    对于本题,我们要思考,什么是大的,什么是小的。

    或许有些人会想设计状态为f[i],表示我从1-i的最小花费,但是仅仅这样是不够的,因为在这之间进小黑屋的不一定要在这之间就出来,他有后效性

    那么什么是没有后效性的呢,如果我们判定这个区间就是全部的大小,他没有后面还在排队了,那么这就不会产生后效影响了

    所以我们对这个方程进行改换定义,定义他为f[i][j],也就是我从i-j的最小花费且不算他前面的数,也就是我每个区间都是从第一个开始的,这样就不会被别的影响了,

    那我们想我们如何转移方程呢?

    在我们的对状态定义之后,不难发现要用区间dp

    那么f[l][r]=min(a[i]*(k-1)+f[i+1][i+k-1]+f[i+k][j]+k*(sum[j]-sum[i+k-1]))

    他的意思是我第l个数我第几个走,我们发现.f[i+1][i+k-1],f[i+k][j]这两个区间都是计算过的,且题目告诉我们先进的最后出来,这样就完美的符合转移的关系

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int inf=0x3f3f3f3f;
    int dp[102][102];
    int a[105];
    int sum[105];
    int main(){
        int t;
        cin>>t;
        int cas=0;
        while(t--){
            cas++;
            int n;
            cin>>n;
            for(int i=1;i<=n;i++)
            cin>>a[i];
            for(int i=1;i<=n;i++)
            sum[i]=sum[i-1]+a[i];
            int len=1;
            int i,j,k;
            for(i=1;i<n;i++){
                for(j=i+1;j<=n;j++)
                dp[i][j]=inf;
            }
            for(len=1;len<=n;len++){
                for(i=1;i+len-1<=n;i++){
                    j=len+i-1;
                    for(k=1;k<=len;k++){
                        dp[i][j]=min(dp[i][j],a[i]*(k-1)+dp[i+1][i+k-1]+dp[i+k][j]+k*(sum[j]-sum[i+k-1]));
                    }
                }
            }
            printf("Case #%d: %d
    ",cas,dp[1][n]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    数论
    平衡树
    矩阵儿快速幂
    分治
    考试
    考试
    匈牙利算法
    SPFA
    倍增
    MySql 技术内幕 (数据库组成和引擎)
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12327494.html
Copyright © 2011-2022 走看看