题意:每个人出场时获得等待时间*值的unhappy值。有个栈换出场顺序。问怎样最小?

一开始的时候觉得在中间取断点,dp[i][j]表示区间全出场后的最小值。那么dp[i][j]=dp[i][k]+dp[k+1][j],但这样是不行的。因为有可能最优解是[i][k]只出场部分,剩一些在栈里,然后再出场别的。

注意到栈有一个性质,如果第一个元素是第3个出栈,那么在它出栈前第2,3个元素已经出栈了。如果第一个元素第k出栈,那么[2,k]必在前k-1个出栈。那么状态转移时就列出所有可能的k。

正:

#pragma comment(linker,"/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
#include <stack>
using namespace std;
const int SZ=1e2+,INF=0x7FFFFFFF;
typedef long long lon;
int n,arr[SZ],sum[SZ],dp[SZ][SZ]; void init()
{
cin>>n;
for(int i=;i<=n;++i)cin>>arr[i],sum[i]=sum[i-]+arr[i];
for(int len=;len<=n;++len)
{
for(int i=;i<=n;++i)
{
int r=i+len-;
if(r>n)break;
dp[i][r]=INF;
for(int k=;k<=len;++k)
{
dp[i][r]=min(dp[i][r],dp[i+][i+k-]+dp[i+k][r]+(k-)*arr[i]+(k)*(sum[r]-sum[i+k-]));
//if(i==1&&r==3)cout<<"dp[i][r]: "<<dp[i][r]<<" "<<dp[i+k][r]<<endl;
}
}
}
// for(int i=1;i<=n;++i)
// {
// for(int j=i;j<=n;++j)
// {
// cout<<"i: "<<i<<"j: "<<j<<" "<<dp[i][j]<<" ";
// }cout<<endl;
// }
cout<<dp[][n]<<endl;
} int main()
{
std::ios::sync_with_stdio();
int casenum;
cin>>casenum;
for(int time=;time<=casenum;++time)
{
cout<<"Case #"<<time<<": ";
init();
}
return ;
}

误:

#pragma comment(linker,"/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
#include <stack>
using namespace std;
const int SZ=1e2+,INF=0x7FFFFFFF;
typedef long long lon;
int n,arr[SZ],sum[SZ],dp[SZ][SZ],st[SZ][SZ]; void init()
{
cin>>n;
for(int i=;i<=n;++i)cin>>arr[i],sum[i]=sum[i-]+arr[i];
for(int len=;len<=n;++len)
{
for(int i=;i<=n;++i)
{
int r=i+len-;
if(r>n)break;
st[i][r]=st[i+][r]+(len-)*arr[i];
}
}
for(int len=;len<=n;++len)
{
for(int i=;i<=n;++i)
{
int r=i+len-;
if(r>n)break;
dp[i][r]=st[i][r-]+(sum[r-]-sum[i-]);
if(i==&&r==)cout<<"h: "<<dp[i][r]<<endl;
for(int k=i;k<r;++k)
{
dp[i][r]=min(dp[i][r],dp[i][k]+st[k+][r-]+max(,(k-i+))*(sum[r-]-sum[k])+(k-i+)*arr[r]);
if(i==&&r==)cout<<"h: "<<dp[i][r]<<endl;
}
}
}
// for(int i=1;i<=n;++i)
// {
// for(int j=i;j<=n;++j)
// {
// cout<<"i: "<<i<<"j: "<<j<<" "<<dp[i][j]<<" ";
// }cout<<endl;
// }
cout<<dp[][n]<<endl;
} int main()
{
std::ios::sync_with_stdio();
int casenum;
cin>>casenum;
for(int time=;time<=casenum;++time)
{
cout<<"Case #"<<time<<": ";
init();
}
return ;
}

hdoj4283 You Are the One的更多相关文章

  1. 专题训练之区间DP

    例题:以下例题部分的内容来自https://blog.csdn.net/my_sunshine26/article/details/77141398 一.石子合并问题 1.(NYOJ737)http: ...

随机推荐

  1. HTML ajax 上传文件限制文件的类型和文件大小

    html    <input type="file" name="excel" id="excel_input" accept=&qu ...

  2. 【Python】Python 网页爬虫 & 文本处理 & 科学计算 & 机器学习 & 数据挖掘兵器谱

    本文转载自:https://www.cnblogs.com/colipso/p/4284510.html 好文 mark http://www.52nlp.cn/python-%E7%BD%91%E9 ...

  3. Linux基础命令---mv

    mv 将文件或者目录移动到另一个地方,或者重命名. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE.openSUSE.Fedora. 1.语法       mv [选项 ...

  4. 音响理论基础入门:Gain(增益)

    谈到放大器就必须先了解增益:一个小的信号Level(电平)经过放大电路成为大的信号Level ,也就是说由小变大之间的差异就叫增益,也叫放大率,反过来的叫衰减率.在音响系统内,一般以信号源的输入电平决 ...

  5. SVN版本服务器搭建

    windows:        https://blog.csdn.net/lu1024188315/article/details/74082227 SVN 的下载地址如下 http://torto ...

  6. keepalived+MySQL高可用集群

    基于keepalived搭建MySQL的高可用集群   MySQL的高可用方案一般有如下几种: keepalived+双主,MHA,MMM,Heartbeat+DRBD,PXC,Galera Clus ...

  7. html模板生成静态页面及模板分页处理

    它只让你修改页面的某一部分,当然这"某一部分"是由你来确定的.美工先做好一个页面,然后我们把这个页面当作模板(要注意的是这个模板就没必要使用EditRegion3这样的代码了,这种 ...

  8. 20145332 MAL_简单后门

    20145332 MAL_简单后门 用NC获取远程主机的shell 2.1.1 Windows获得Linux的权限 首先要在Windows主机下安装ncat.exe,安装完成后需要配置环境变量path ...

  9. VS中自动选择x86或x64的dll

    http://www.cnblogs.com/lzjsky/archive/2010/09/06/1819321.html 原来使用Win7的32位系统,进行C#工程的开发,后来重装系统,换成了win ...

  10. vim 操作快捷键 待更~

    shift + g 文件尾 ------ gdb p print start 从main函数开始 n next换行 s step 进入函数