4380: [POI2015]Myjnie
Time Limit: 40 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 327 Solved: 167
[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
7 5
1 4 7
3 7 13
5 6 20
6 7 1
1 2 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
5 5 13 13 20 20 13
这应该是dp白痴BJ做过最强的区间dp了...
我们发现 决策与其区间最小值有关 所以把c搞进去
所以我们用f[i][j][k] 表示在区间[i,j]内所有权值>=k的最大收益
之后怎么转移呐
考虑[l,r]每次从[l+1,r] [l,r-1]转移 //手动滑稽
枚举一个点k
f[l][r][j]=max(f[l][k-1]+f[k+1][r]+c[j]*num[k][j])
其中num的含义是
l<=a<=k<=b<=r 且可以接受价格>=c[j]的个数
至于输出方案 就中间记下决策点 然后dfs一边就好了
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}
const int N=55,M=4010,inf=0X3f3f3f3f;
struct node
{
int a,b,c;
friend bool operator <(const node &x,const node &y)
{return x.c<y.c;}
}p[N];
int f[N][N][M],g[N][N][M],last[N][N][M];
int num[N][M];
int val[N];
void dfs(int l,int r,int lim)
{
if(l>r) return ;
int tmp[2];
tmp[0]=g[l][r][lim],tmp[1]=last[l][r][lim];
val[tmp[0]]=p[tmp[1]].c;
dfs(l,tmp[0]-1,tmp[1]);dfs(tmp[0]+1,r,tmp[1]);
}
int main()
{
int n=read(),m=read();
register int l,r,i,j,len;
for(i=1;i<=m;++i)
p[i].a=read(),p[i].b=read(),p[i].c=read();
sort(p+1,p+1+m);
for(l=1;l<=n;++l)
for(r=l;r<=n;++r)
for(j=1;j<=m;++j)
f[l][r][j]=-inf;
for(len=0;len<n;++len)
for(l=1;l+len<=n;++l)
{
r=l+len;
for(i=l;i<=r;++i)
for(j=1;j<=m;++j)
num[i][j]=0;
for(j=1;j<=m;++j)
if(p[j].a>=l && p[j].b<=r)
for(i=p[j].a;i<=p[j].b;++i)
num[i][j]++;
for(i=l;i<=r;++i)
for(j=m;j;j--)
num[i][j]+=num[i][j+1];
for(i=l;i<=r;++i)
for(j=1;j<=m;++j)
if(f[l][r][j]<f[l][i-1][j]+f[i+1][r][j]+p[j].c*num[i][j])
f[l][r][j]=f[l][i-1][j]+f[i+1][r][j]+p[j].c*num[i][j],
g[l][r][j]=i,last[l][r][j]=j;
for(j=m;j;j--)
if(f[l][r][j]<f[l][r][j+1])
f[l][r][j]=f[l][r][j+1],
g[l][r][j]=g[l][r][j+1],last[l][r][j]=last[l][r][j+1];
}
dfs(1,n,1);
print(f[1][n][1]);putchar('\n');
for(i=1;i<=n;++i)
print(val[i]),putchar(' ');
return 0;
}