You Are The One

题意:有n个人准备按顺序上台,上台前有个小黑屋(先进后出,即栈),可以被安排进去等待,也可以直接上台,一个人一旦被安排进去,后面的人就可以先上台(小黑屋无限大)。每个人有一个愤怒值angry,如果他是第k个上台的,那么他的怒气和就是(k-1)*angry,如何运用小黑屋安排上台顺序,使得这n个人的怒气总和最小。

思路:这是一道区间dp题(这几天做的都是区间dp的专题,不是就见鬼了),状态很容易想到,用f[l][r],表示l~rr-l+1个人的最小怒气总和,那么如何转移,其实区间dp大概的套路也就是三个for( for len ; for l,r ; for k (l,r) ),而这题其中的小细节也比较容易观察到,那么问题来了,这也是为什么这题区间dp拿来写的原因,一般的k枚举都是lr来划分区间,但是这题显然没有什么用,为什么没用?因为要用小黑屋啊!如果直接枚举断点,而这题的l, r点是没什么关系的(如果真的有,个人感觉也很难推出,因为每个人的出场顺序其实是不一定的),怎么算出最优?(不用小黑屋也可以看做进去马上出来,问题不大),那么考虑到一个问题,既然出场顺序不一定,那k就枚举出场顺序吧,显然区间l~r的一个人出场顺序就只有r-l+1种,因为如果只有len个人,怎么做到第len+1出场?(一场跑步比赛,你超越了最后一名,你是第几!),至此,转移的for考虑完了,那么这个k来枚举谁呢?第一个?最后一个?随便一个?其实,随便一个都可以,因为最后区间最优,其实顺序是定的,所以先枚举谁都可以,那么就枚举这个区间的第一个吧,因为好写。可以想想,第一个人第k个出场,是不是1~1+k-1比他早出场,1+k~end在他后面出场(所以这些人都多等待了k个人,因而怒气值要多加上k次),那么转移式子就出来了。

题外:写这题的契机其实有二,一是昨天听同学说了一题区间dp挺有意思的去补了一发,发现自己竟然写出来了dp,说出来是有点开心的,虽然那题并不复杂。而之前一直很害怕dp,觉得能想出来转移的(当然是要能A的正解,瞎想的没有意义)简直就是神仙。最近真的认真思考了一些dp题,发现从简入繁,其实dp挺有意思的,而且个人感觉做dp最大的收益就是很容易看懂别人写的代码(不只是dp的),因为其实dp挺锻炼思维的,一旦开始思考了,理解能力肯定不断地提升。二就是觉得这题区间dp的for套路有意思,k是来枚举顺序的,和别的区间dp(目前自己做到的)不太一样,就放了上来。


Codes:

#include <bits/stdc++.h>
#define pb push_back
#define de(x) cout << #x << " = " << x << endl
#define clr(a,b) memset(a,b,sizeof(a))
using namespace std; typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 110; int f[N][N];
int a[N], pr[N]; int main()
{
int n;
int cas = 1;
int t;
scanf("%d", &t);
while ( t -- )
{
scanf("%d", &n);
pr[0] = 0;
for ( int i = 1; i <= n; i ++ )
{
scanf("%d", &a[i]);
pr[i] = pr[i-1] + a[i];
f[i][i] = 0;
} for ( int len = 2; len <= n; len ++ )
{
for ( int l = 1, r; ( r = l + len - 1 ) <= n; l ++ )
{
f[l][r] = INF;
for ( int k = 1; k <= len; k ++ )
{
f[l][r] = min( f[l][r], (k-1)*a[l] + f[l+1][l+k-1] + f[l+k][r] + k*(pr[r]-pr[l+k-1]) );
}
}
}
printf("Case #%d: %d\n", cas++, f[1][n]);
}
return 0;
}

dp_c_区间dp_g的更多相关文章

  1. ASP.NET Core应用针对静态文件请求的处理[2]: 条件请求与区间请求

    通过调用ApplicationBuilder的扩展方法UseStaticFiles注册的StaticFileMiddleware中间件帮助我们处理针对文件的请求.对于StaticFileMiddlew ...

  2. SQL Server 随机数,随机区间,随机抽取数据rand(),floor(),ceiling(),round(),newid()函数等

    在查询分析器中执行:select rand(),可以看到结果会是类似于这样的随机小数:0.36361513486289558,像这样的小数在实际应用中用得不多,一般要取随机数都会取随机整数.那就看下面 ...

  3. codevs 1082 线段树练习 3(区间维护)

    codevs 1082 线段树练习 3  时间限制: 3 s  空间限制: 128000 KB  题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...

  4. codevs 1082 线段树区间求和

    codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...

  5. [LeetCode] Find Right Interval 找右区间

    Given a set of intervals, for each of the interval i, check if there exists an interval j whose star ...

  6. [LeetCode] Non-overlapping Intervals 非重叠区间

    Given a collection of intervals, find the minimum number of intervals you need to remove to make the ...

  7. [LeetCode] Data Stream as Disjoint Intervals 分离区间的数据流

    Given a data stream input of non-negative integers a1, a2, ..., an, ..., summarize the numbers seen ...

  8. [LeetCode] Count of Range Sum 区间和计数

    Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusive.Ra ...

  9. [LeetCode] Summary Ranges 总结区间

    Given a sorted integer array without duplicates, return the summary of its ranges. For example, give ...

随机推荐

  1. jsonarray 循环

    JSONArray groupList = JSON.parseArray(st1); for (int i=0;i<groupList.size();i++){ JSONObject json ...

  2. 【转】Keepalived无法绑定VIP故障排查经历

    一 故障描述 我在台湾合作方给定的两台虚拟机上部署HAProxy+Keepalived负载均衡高可用方案.在配置完Keepalived后,重新启动Keepalived,Keepalived没有绑定VI ...

  3. python基础-第八篇-8.1初识Socket

    socket基础 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. so ...

  4. JavaScript Big-Int

    这个库是为JavaScript中的大整数操作,如加,减,乘,除,mod,比较等. 这个库的原理是模拟笔和纸的操作,你可以操作整数,大到你的RAM允许. 例 var bigInt = require(' ...

  5. SIP中的 session, dialog 及 transaction 的解释

    http://stackoverflow.com/questions/35133331/difference-between-session-dialog-and-transaction-in-sip ...

  6. java 多线程 day07 多线程共享数据

    /** * Created by chengtao on 17/12/3. * 多个线程 如何共享数据? * 常见实例:多个窗口同时售卖火车票 */public class Thread0701_Mu ...

  7. ACM零散知识

    定理与方法专区: 1.两点间的曼哈顿距离如果为偶数,那么两点间可以走偶数步到达 2.求小于等于n 的素数的个数.(即欧拉函数) 100=(2^2)*(5^2)    num[100]=(2+1)*(2 ...

  8. Linux系统——awk命令

    awk命令不仅仅是Linux系统的命令,也是一种编程语言,用来处理数据和生成报告(Exel),处理的数据可以是一个或多个文件(标准输入和管道获取标准输入).可在命令行上编辑操作,也可以写成awk程序运 ...

  9. SQL Server窗口框架——ROWS、RANGE

    说到窗口框架就不得不提起开窗函数. 开窗函数支持分区.排序和框架三种元素,其语法格式如下: OVER ( [ <PARTITION BY clause> ] [ <ORDER BY ...

  10. idea打jar包-MapReduce作业提交到hadoop集群执行

    https://blog.csdn.net/jiaotangX/article/details/78661862 https://liushilang.iteye.com/blog/2093173