BZOJ 4380 Myjnie 区间DP
4380: [POI2015]Myjnie
Time Limit: 40 Sec Memory Limit: 256 MBSec Special Judge
Submit: 162 Solved: 82
[Submit][Status][Discuss]
Description
有n家洗车店从左往右排成一排,每家店都有一个正整数价格p[i]。
有m个人要来消费,第i个人会驶过第a[i]个开始一直到第b[i]个洗车店,且会选择这些店中最便宜的一个进行一次消费。但是如果这个最便宜的价格大于c[i],那么这个人就不洗车了。
请给每家店指定一个价格,使得所有人花的钱的总和最大。
Input
第一行包含两个正整数n,m(1<=n<=50,1<=m<=4000)。
接下来m行,每行包含三个正整数a[i],b[i],c[i](1<=a[i]<=b[i]<=n,1<=c[i]<=500000)
Output
第一行输出一个正整数,即消费总额的最大值。
第二行输出n个正整数,依次表示每家洗车店的价格p[i],要求1<=p[i]<=500000。
若有多组最优解,输出任意一组。
Sample Input
1 4 7
3 7 13
5 6 20
6 7 1
1 2 5
Sample Output
5 5 13 13 20 20 13
HINT
Source
Solution
这个区间DP的思路十分神奇。
设G[l][r][i]为区间[l, r]中最小值为k的最优值,F[l][r][i] = max{G[l][r][j]} (j >= i)。
转移:F[l][r][i] = max{F[l][k-1]+F[k+1][r]+c[i]*cnt[k][i]} (cnt[k][i]就是指c[j]>=i且在区间[l,r]中且跨越点k的个数)
对于方案的记录,我们只需要在转移的时候记录,最后再从最优解开始dfs就可以了。
但是千万要注意的是,所有合法的情况初始化为-INF。不这样做的话,就构不出方案,把f转为0的时候就把方案给记录下来了。
Code
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm> using namespace std; #define FIO "a"
#define REP(i, a, b) for (int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
#define DWN(i, a, b) for (int i = (a), i##_end_ = (b); i >= i##_end_; --i)
#define mset(a, b) memset(a, b, sizeof(a))
const int maxn = , maxm = , INF = 0x3fffffff;
int n, m, a[maxm], b[maxm], c[maxm];
int t[maxm], t_cnt;
int f[maxn][maxn][maxm], cnt[maxn][maxm], from[maxn][maxn][maxn], las[maxn][maxn][maxn];
int ans[maxn]; void dfs(int l, int r, int k)
{
if (l > r) return ;
ans[from[l][r][k]] = t[las[l][r][k]];
dfs(l, from[l][r][k]-, las[l][r][k]);
dfs(from[l][r][k]+, r, las[l][r][k]);
} int main()
{
// freopen(FIO ".in", "r", stdin);
// freopen(FIO ".out", "w", stdout);
scanf("%d %d", &n, &m);
t_cnt = ;
REP(i, , m) scanf("%d %d %d", &a[i], &b[i], &c[i]), t[++t_cnt] = c[i];
sort(t+, t+t_cnt+);
int temp = t_cnt, x; t_cnt = ;
REP(i, , temp) if (t[i] != t[i-]) t[++t_cnt] = t[i];
REP(i, , m) c[i] = lower_bound(t+, t+t_cnt+, c[i])-t;
REP(i, , n) REP(j, i, n) REP(k, , m) f[i][j][k] = -INF;
REP(len, , n)
REP(l, , n-len+)
{
int r = l+len-;
REP(i, l, r) REP(j, , m) cnt[i][j] = ;
REP(i, , m)
if (a[i] >= l && b[i] <= r)
REP(j, a[i], b[i]) cnt[j][c[i]] ++;
REP(i, l, r) DWN(j, m-, ) cnt[i][j] += cnt[i][j+];
REP(k, l, r)
REP(i, , m)
if (f[l][k-][i]+f[k+][r][i]+t[i]*cnt[k][i] > f[l][r][i])
f[l][r][i] = f[l][k-][i]+f[k+][r][i]+t[i]*cnt[k][i],
from[l][r][i] = k, las[l][r][i] = i;
DWN(i, m-, )
if (f[l][r][i] < f[l][r][i+])
f[l][r][i] = f[l][r][i+],
from[l][r][i] = from[l][r][i+], las[l][r][i] = las[l][r][i+];
}
printf("%d\n", f[][n][]);
dfs(, n, );
REP(i, , n) printf("%d%c", ans[i], i == n ? '\n' : ' ');
return ;
}
BZOJ 4380 Myjnie 区间DP的更多相关文章
- 【BZOJ-4380】Myjnie 区间DP
4380: [POI2015]Myjnie Time Limit: 40 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 162 Solved: ...
- 【BZOJ4380】[POI2015]Myjnie 区间DP
[BZOJ4380][POI2015]Myjnie Description 有n家洗车店从左往右排成一排,每家店都有一个正整数价格p[i].有m个人要来消费,第i个人会驶过第a[i]个开始一直到第b[ ...
- [bzoj] 1068 压缩 || 区间dp
原题 f[i][j][0/1]表示i-1处有一个M,i到j压缩后的长度,0/1表示i到j中有没有m. 初始为j-i+1 f[i][j][0]=min(f[i][j][0],f[i][k][0]+j-k ...
- 【BZOJ 4380】4380: [POI2015]Myjnie (区间DP)
4380: [POI2015]Myjnie Description 有n家洗车店从左往右排成一排,每家店都有一个正整数价格p[i].有m个人要来消费,第i个人会驶过第a[i]个开始一直到第b[i]个洗 ...
- BZOJ 4380 [POI2015]Myjnie | DP
链接 BZOJ 4380 题面 有n家洗车店从左往右排成一排,每家店都有一个正整数价格p[i]. 有m个人要来消费,第i个人会驶过第a[i]个开始一直到第b[i]个洗车店,且会选择这些店中最便宜的一个 ...
- BZOJ.4897.[Thu Summer Camp2016]成绩单(区间DP)
BZOJ 显然是个区间DP.令\(f[l][r]\)表示全部消掉区间\([l,r]\)的最小花费. 因为是可以通过删掉若干子串来删子序列的,所以并不好直接转移.而花费只与最大最小值有关,所以再令\(g ...
- [BZOJ 1652][USACO 06FEB]Treats for the Cows 题解(区间DP)
[BZOJ 1652][USACO 06FEB]Treats for the Cows Description FJ has purchased N (1 <= N <= 2000) yu ...
- [BZOJ 1260][CQOI2007]涂色paint 题解(区间DP)
[BZOJ 1260][CQOI2007]涂色paint Description 假设你有一条长度为5的木版,初始时没有涂过任何颜色.你希望把它的5个单位长度分别涂上红.绿.蓝.绿.红色,用一个长度为 ...
- [BZOJ 1032][JSOI 2007]祖玛 题解(区间DP)
[BZOJ 1032][JSOI 2007]祖玛 Description https://www.lydsy.com/JudgeOnline/problem.php?id=1032 Solution ...
随机推荐
- go 指针类型
变量和内存地址 每个变量都有内存地址,可以说通过变量来操作对应大小的内存 var a int32 a = fmt.Printf(“%d\n”, a) fmt.Printf(“%p\n”, &a ...
- 如何更方便的查看Linux内核代码的更新记录【转】
转自:http://blog.csdn.net/lee244868149/article/details/44302819 Linux内核的更新非常的快,如何快速的了解这些更新呢?最一般的办法就是把新 ...
- Linux的bg和fg命令 ---让程序在前台后台之间切换
Linux的bg和fg命令 我们都知道,在 Windows 上面,我们要么让一个程序作为服务在后台一直运行,要么停止这个服务.而不能让程序在前台后台之间切换.而 Linux 提供了 fg 和 bg 命 ...
- [Android Studio] Android Studio如何快速生成get,set,tostring,构造函数
刚开始使用Android Studio时,在创建一个javabean时,很习惯的在JavaBean类中,右键去找生成get,set等选项.但是很遗憾,找不到. 那这边如何快速的set,get或者生成构 ...
- 2->集群架构主机优化流程
集群架构优化流程: 有道笔记分享链接
- Win10搜索不能用
使用win10进行搜索时,一直显示win10特色的滚动条,但就是检索不出东西,我的主要是检索不到windows的内容: (个人感觉使用win10检索网页内容不太专业,就关闭了Web搜索) 最后有发现网 ...
- java基础19 导包和“命令行”打jar包
1.导包 1.1.包 java中的包就相当于Windows文件夹 编译格式:javac -d . 类名.java 1.2.包的作用 1.解决了类名重复冲突的问题 2.便于软件版本的 ...
- FZU 1901 Period II(KMP循环节+公共前后缀)
题目链接:http://acm.fzu.edu.cn/problem.php?pid=1901 题目大意:题目大意求出所有p满足s[i]=s[i+p](i<=len-p) 解题思路: 其实就是要 ...
- 开源的python机器学习模块
1. Scikit-learn Scikit-learn 是基于Scipy为机器学习建造的的一个Python模块,他的特色就是多样化的分类,回归和聚类的算法包括支持向量机,逻辑回归,朴素贝叶斯分类器, ...
- Flask SQLAlchemy & model
Flask-SQLAlchemy Flask-SQLAlchemy库让flask更方便的使用SQLALchemy,是一个强大的关系形数据库框架,既可以使用orm方式操作数据库,也可以使用原始的SQL命 ...