BZOJ4380 POI2015 Myjnie
2016-11-12 16:46
711 查看
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]≤5×105)
Output
第一行输出一个正整数,即消费总额的最大值。
第二行输出n个正整数,依次表示每家洗车店的价格p[i],要求1<=p[i]<=500000。
若有多组最优解,输出任意一组。
Sample Input
7 5
1 4 7
3 7 13
5 6 20
6 7 1
1 2 5
Sample Output
43
5 5 13 13 20 20 13
Solution:
玄学三维dp,膜Claris大犇。
还是提醒自己先不要考虑方案输出。事实证明先考虑方案就会想到贪心爆搜等奇怪的思路上。
对于当前这个询问区间,它的贡献是vali={min[L,R]0min[L,R]≤Limitimin[L,R]>Limiti。
思考对象为区间的话感觉没有什么思路,我们考虑每个洗车店对答案的贡献:在什么情况下,哪些车辆会在当前的洗车店消费?
在某段区域内,当前这个洗车店为最小值,就会导致在该区域内并且经过该洗车店的车辆在此处进行消费。
于是我们按照上述内容进行dp就好了,定义dp[L][R][k]表示在区间[L,R]内,该区间的最小值最小为k时,全部路程在[L,R]内的汽车的最优总贡献。之后枚举哪一家洗车店的价格定为k,统计区间经过当前洗车店,并且Limiti≥k的车辆总数,记为h[i][k]。于是得到转移方程式(显然这个k我们需要离散,对应的数组在我的代码中记作res[k]):
dp[L][R][k]=max{dp[L][p−1][k]+dp[p+1][R][k]+res[k]×h[p][k]dp[L][R][w]p∈[L,R]w∈[k,m]
这样最优解就得到了,接下来打印方案的话,我们存储从哪个洗车店转移和此时洗车店的最优定价(因为我们关于dp的定义没有确定当前枚举的消费值就是最优解……)。类似二叉树一样不断将区间劈成两部分递归处理即可。对应到我的代码中分别为f数组和v数组。
最后总复杂度为O(n3m)(果然数据范围小没什么好事情……)。
就当做是补充Claris大犇短小的题解吧2333
有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]≤5×105)
Output
第一行输出一个正整数,即消费总额的最大值。
第二行输出n个正整数,依次表示每家洗车店的价格p[i],要求1<=p[i]<=500000。
若有多组最优解,输出任意一组。
Sample Input
7 5
1 4 7
3 7 13
5 6 20
6 7 1
1 2 5
Sample Output
43
5 5 13 13 20 20 13
Solution:
玄学三维dp,膜Claris大犇。
还是提醒自己先不要考虑方案输出。事实证明先考虑方案就会想到贪心爆搜等奇怪的思路上。
对于当前这个询问区间,它的贡献是vali={min[L,R]0min[L,R]≤Limitimin[L,R]>Limiti。
思考对象为区间的话感觉没有什么思路,我们考虑每个洗车店对答案的贡献:在什么情况下,哪些车辆会在当前的洗车店消费?
在某段区域内,当前这个洗车店为最小值,就会导致在该区域内并且经过该洗车店的车辆在此处进行消费。
于是我们按照上述内容进行dp就好了,定义dp[L][R][k]表示在区间[L,R]内,该区间的最小值最小为k时,全部路程在[L,R]内的汽车的最优总贡献。之后枚举哪一家洗车店的价格定为k,统计区间经过当前洗车店,并且Limiti≥k的车辆总数,记为h[i][k]。于是得到转移方程式(显然这个k我们需要离散,对应的数组在我的代码中记作res[k]):
dp[L][R][k]=max{dp[L][p−1][k]+dp[p+1][R][k]+res[k]×h[p][k]dp[L][R][w]p∈[L,R]w∈[k,m]
这样最优解就得到了,接下来打印方案的话,我们存储从哪个洗车店转移和此时洗车店的最优定价(因为我们关于dp的定义没有确定当前枚举的消费值就是最优解……)。类似二叉树一样不断将区间劈成两部分递归处理即可。对应到我的代码中分别为f数组和v数组。
最后总复杂度为O(n3m)(果然数据范围小没什么好事情……)。
就当做是补充Claris大犇短小的题解吧2333
#include <cstdio> #include <cstring> #include <algorithm> #define N 55 #define M 4005 template <class temp> inline bool check_max(temp &a,temp b){ if(a>=b)return false; a=b;return true; } int dp [M],v [M],f [M],h [M]; int a[M],b[M],c[M],res[M]; int ans[M]; void dfs(int l,int r,int col){ if(l>r)return; int mid=f[l][r][col]; ans[mid]=v[l][r][col]; col=v[l][r][col]; dfs(l,mid-1,col),dfs(mid+1,r,col); } int main(){ int n,m; scanf("%d %d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d %d %d",&a[i],&b[i],&c[i]); res[i]=c[i]; } std::sort(res+1,res+m+1); for(int i=1;i<=m;i++) c[i]=std::lower_bound(res+1,res+m+1,c[i])-res; for(int t=1;t<=n;t++) for(int l=1;l+t-1<=n;l++){ int r=l+t-1; for(int i=l-1;i<=r;i++) for(int j=1;j<=m;j++)h[i][j]=0; for(int i=1;i<=m;i++) if(l<=a[i]&&b[i]<=r) h[a[i]][c[i]]++,h[b[i]+1][c[i]]--; for(int j=1;j<=m;j++) for(int i=l;i<=r;i++)h[i][j]+=h[i-1][j]; for(int i=l;i<=r;i++) for(int j=m;j>=1;j--)h[i][j]+=h[i][j+1]; for(int k=m;k>=1;k--){ f[l][r][k]=l,v[l][r][k]=k; for(int i=l;i<=r;i++) if(check_max(dp[l][r][k],dp[l][i-1][k]+dp[i+1][r][k]+res[k]*h[i][k])) f[l][r][k]=i,v[l][r][k]=k; } for(int k=m-1;k>=1;k--) if(check_max(dp[l][r][k],dp[l][r][k+1])) f[l][r][k]=f[l][r][k+1],v[l][r][k]=v[l][r][k+1]; } printf("%d\n",dp[1] [1]); dfs(1,n,1); printf("%d",(!ans[1])?res[m]:res[ans[1]]); for(int i=2;i<=n;i++) printf(" %d",(!ans[i])?res[m]:res[ans[i]]); putchar('\n'); }
相关文章推荐
- BZOJ4380[POI2015] Myjnie
- BZOJ4380: [POI2015]Myjnie
- BZOJ4380: [POI2015]Myjnie
- 【jzoj4931】【bzoj4380】【POI2015】【Myjnie】【动态规划】
- [BZOJ 4380] POI 2015 Myjnie
- 【bzoj4380】[POI2015]Myjnie
- BZOJ 4380 [POI2015]Myjnie | DP
- [BZOJ4380][POI2015] Myjnie 区间DP
- 【BZOJ4380】[POI2015]Myjnie 区间DP
- 【BZOJ 4380】4380: [POI2015]Myjnie (区间DP)
- 4380: [POI2015]Myjnie
- BZOJ 4380: [POI2015]Myjnie 区间dp
- bzoj 4381: [POI2015]Odwiedziny 分块+树链剖分
- BZOJ 3748: [POI2015]Kwadraty
- 【BZOJ 3747】 3747: [POI2015]Kinoman (线段树)
- [BZOJ3747][POI2015]Kinoman
- BZOJ 4384: [POI2015]Trzy wieże
- [分块 暴力 树] BZOJ 4381 [POI2015]Odwiedziny
- bzoj 3747 [POI2015]Kinoman
- bzoj3747[POI2015]Kinoman