[POI2015]Myjnie
2018-09-02 20:52
225 查看
[POI2015]Myjnie
题目大意:
有\(n(n\le50)\)家洗车店从左往右排成一排,每家店都有一个正整数价格\(d_i\)。
有\(m(m\le4000)\)个人要来消费,第\(i\)个人会选择\(a_i\sim b_i\)这些店中最便宜的一个进行一次消费。但是如果这个最便宜的价格大于\(c_i\),那么这个人就不洗车了。
请给每家店指定一个价格,使得所有人花的钱的总和最大。
思路:
将\(c\)离散化后进行区间DP。
用\(f_{i,j,k}\)表示区间\([i,j]\)最小值为\(k\)的最大收益,\(g_{i,j,k}\)表示\(f\)的后缀\(\max\),\(h_{i,j}\)表示当前区间内经过\(i\)点,费用限制\(\ge j\)的人数。
设\(k\)对应的离散化前原数为\(t_k\),枚举\(k\)出现的位置\(x\),转移方程为:
\[
f_{i,j,k}=\max\{g_{i,x-1,k}+g_{x+1,j,k}+h_{x,k}\times t_k\}。
\]
由于要构造一种方案,在DP时记录转移即可。
时间复杂度\(\mathcal O(n^3m)\)。
源代码:
#include<cstdio> #include<cctype> #include<algorithm> inline int getint() { register char ch; while(!isdigit(ch=getchar())); register int x=ch^'0'; while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); return x; } const int N=51,M=4001; int a[M],b[M],c[M],d ,tmp[M],f [M],g [M],p [M],last [M],h [M]; void dfs(const int &i,const int &j,const int &k) { const int &p=::p[i][j][k]; if(i!=p) dfs(i,p-1,last[i][j][k]); if(j!=p) dfs(p+1,j,last[i][j][k]); d[p]=tmp[last[i][j][k]]; } int main() { const int n=getint(),m=getint(); for(register int i=1;i<=m;i++) { a[i]=getint(); b[i]=getint(); tmp[++tmp[0]]=c[i]=getint(); } std::sort(&tmp[1],&tmp[tmp[0]]+1); tmp[0]=std::unique(&tmp[1],&tmp[tmp[0]]+1)-&tmp[1]; for(register int i=1;i<=m;i++) { c[i]=std::lower_bound(&tmp[1],&tmp[tmp[0]]+1,c[i])-tmp; } for(register int i=n;i>=1;i--) { for(register int j=i;j<=n;j++) { for(register int k=i;k<=j;k++) { std::fill(&h[k][1],&h[k][tmp[0]]+1,0); } for(register int k=1;k<=m;k++) { if(i<=a[k]&&b[k]<=j) { for(register int i=a[k];i<=b[k];i++) h[i][c[k]]++; } } for(register int k=i;k<=j;k++) { for(register int i=tmp[0];i>1;i--) h[k][i-1]+=h[k][i]; } for(register int k=tmp[0];k>=1;k--) { for(register int x=i;x<=j;x++) { const int t=g[i][x-1][k]+g[x+1][j][k]+h[x][k]*tmp[k]; if(t>=f[i][j][k]) { f[i][j][k]=t; p[i][j][k]=x; } } g[i][j][k]=f[i][j][k]; last[i][j][k]=k; if(k!=tmp[0]&&g[i][j][k+1]>g[i][j][k]) { g[i][j][k]=g[i][j][k+1]; p[i][j][k]=p[i][j][k+1]; last[i][j][k]=last[i][j][k+1]; } } } } dfs(1,n,1); printf("%d\n",g[1] [1]); for(register int i=1;i<=n;i++) { printf("%d%c",d[i]," \n"[i==n]); } return 0; }
相关文章推荐
- bzoj4380: [POI2015]Myjnie
- BZOJ4380 : [POI2015]Myjnie
- BZOJ4380[POI2015] Myjnie
- BZOJ4380 POI2015 Myjnie
- 【bzoj4380】[POI2015]Myjnie
- [BZOJ 4380] POI 2015 Myjnie
- BZOJ4380: [POI2015]Myjnie
- 4380: [POI2015]Myjnie
- 【jzoj4931】【bzoj4380】【POI2015】【Myjnie】【动态规划】
- BZOJ4380: [POI2015]Myjnie
- BZOJ3748 : [POI2015]Kwadraty
- bzoj3750 [POI2015]Pieczęć
- bzoj 4385: [POI2015]Wilcze doły
- 【BZOJ 3747】 3747: [POI2015]Kinoman (线段树)
- BZOJ4379[POI2015] Modernizacja autostrady
- bzoj3750: [POI2015]Pieczęć
- BZOJ4384: [POI2015]Trzy wieże 记忆化搜索
- [BZOJ4383][POI2015]Pustynia (拓扑排序)
- BZOJ4385: [POI2015]Wilcze doły
- bzoj 4385: [POI2015]Wilcze doły【单调栈】