You Are the One HDU

来源:互联网 发布:星际皆知你爱我网盘 编辑:程序博客网 时间:2024/06/10 07:27

http://acm.hdu.edu.cn/showproblem.php?pid=4283.

题意:给一个序列数,按顺序不断的删除这些数,删除的消费为(index-1)*a[i]  index为删除的次序(第几个删除),a[i] 为这个数的值,    你有一个栈,可以暂时存放一些数,也就是可以改变原来数删除的顺序,求最小的总消费

加入你有序列  1  2  3  4

我可以先把1删除(这时消费为(1-1)*1=0),把2放入栈内,这时可以选择把3放入栈内,也可以选择把3删除(这时消费为(2-1)*3=3),也可以选择把栈顶的2出队(2-1)*2=2)。等等

思路:区间dp

dp [i][j] 表示不考虑其他元素,删除i到j内元素的需要的最小总消费

sum [i][j] 表示i到j这段区间和(其实一维前缀和就可以)

t [i][j] 表示不考虑其他元素,按从j到i的顺序删除这些元素的消费和

dp[i][j] = min(dp[i] [k] + dp[k+1] [j] + sum[k+1] [j] * (k-i+1)  ,  dp[k+1] [j] + t[i] [j] + sum[i] [j] * (j-k) )

其中dp[i] [k] + dp[k+1] [j] + sum[k+1] [j] * (k-i+1)是指先删除i到k段,在删除k+1到j段,

dp[k+1] [j] + t[i] [j] + sum[i] [j] * (j-k)是指先把i到j放入栈内,删除k+1到j段,在删除栈内(也就是逆序删除)

#include<bits/stdc++.h>#define eps 1e-9#define PI 3.141592653589793#define bs 1000000007#define bsize 256#define MEM(a) memset(a,0,sizeof(a))typedef long long ll;using namespace std;int dp[200][200];int a[200];int sum[200][200];int temp[2][200][200];void init(int x){    int i,j;    for(i=0;i<x;i++)    {        sum[i][i]=a[i];        temp[0][i][i]=0;        for(j=i+1;j<x;j++)        {            sum[i][j]=sum[i][j-1]+a[j];            temp[0][i][j]=temp[0][i][j-1]+(j-i)*a[j];        }    }    for(i=0;i<x;i++)    {        temp[1][i][i]=0;        for(j=i-1;j>=0;j--)        {            temp[1][j][i]=temp[1][j+1][i]+(i-j)*a[j];        }    }}int main(){int T,j,k,kk,i,n,ans=0;cin>>T;for(int t=1;t<=T;t++){memset(dp,0,sizeof(dp));ans=0;cin>>n;for(i=0;i<n;i++){cin>>a[i];}init(n);for(i=1;i<=n-1;i++){for(j=0;j+i<n;j++){int minn;dp[j][j+i]=min(temp[0][j][j+i],temp[1][j][j+i]);for(k=j;k<j+i;k++){    int now=min(dp[j][k]+dp[k+1][j+i]+(k-j+1)*sum[k+1][j+i],dp[k+1][j+i]+temp[1][j][k]+(j+i-k)*sum[j][k]);dp[j][j+i]=min(dp[j][j+i],now);}}}printf("Case #%d: %d\n",t,dp[0][n-1]);}return 0; }


原创粉丝点击