码迷,mamicode.com
首页 > 其他好文 > 详细

线状DP(石子归并)

时间:2016-03-04 18:58:25      阅读:156      评论:0      收藏:0      [点我收藏+]

标签:

题意:有N堆石子,现要将石子有序的合并成一堆,规定如下:每次只能移动相邻的2堆石子合并,合并花费为新合成的一堆石子的数量。求将这N堆石子合并成一堆的总花费最小(或最大)。

dp[i][j]为从i到j的最小代价;sum为i到j的和;k用于分割dp[i][j];

动态转移方程为:dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[i][j]);

#include <iostream>
#include <algorithm>
#include <stdlib.h>
#include <time.h>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <set>

#define c_false ios_base::sync_with_stdio(false); cin.tie(0)
#define INF 0x3f3f3f3f
#define INFL 0x3f3f3f3f3f3f3f3f
#define zero_(x,y) memset(x , y , sizeof(x))
#define zero(x) memset(x , 0 , sizeof(x))
#define MAX(x) memset(x , 0x3f ,sizeof(x))
using namespace std ;
#define N 505
typedef long long LL ;
int dp[N][N],sum[N][N],a[N];
int main(){
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n;
    cin>>n;
    zero(sum);
    zero(dp);
    for(int i = 1; i <= n; i++) cin>>a[i];
    for(int i = 1; i < n; i++){
        sum[i][i] = a[i];
        for(int j = i+1; j <= n; j++){
            sum[i][j] = sum[i][j-1] + a[j];
            //printf("%5d%5d%5d\n",i,j,sum[i][j]);
        }
    }
    int j;
    for(int len = 1; len < n; len++){
        for(int i = 1; i < n-len+1; i++ ){
            j = i+len;
            dp[i][j] = INF;
            for(int k = i; k < j; k++){
                dp[i][j] = min(dp[i][j], dp[i][k]+dp[k+1][j]+sum[i][j]);
               // printf("%5d%5d%5d%5d\n",i,j,len,dp[i][j]);
            }
        }
    }
    cout << dp[1][n]<<endl;
    return 0;
}

 

线状DP(石子归并)

标签:

原文地址:http://www.cnblogs.com/yoyo-sincerely/p/5242906.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!