您的位置:首页 > 其它

4380: [POI2015]Myjnie

2018-02-26 22:06 302 查看
题目链接

题目大意:有n家洗车店,每家店都有一个正整数价格p[i]。

有m个人要来消费,第i个人会选择a[i]~b[i]这些店中最便宜的一个进行一次消费。但是如果这个最便宜的价格大于c[i],那么这个人就不洗车了。请给每家店指定一个价格,使得所有人花的钱的总和最大。

题解:比较烦的区间dp……

Orz 题解

我的收获:常规操作……

#include <bits/stdc++.h>
using namespace std;

#define Rep(x,n,m) for(int x=n;x<=m;x++)
#define Gep(x,n,m) for(int x=n;x>=m;x--)

const int INF=1e8;
const int N=55;
const int MX=4005;

int n,m;
int a[MX],b[MX],c[MX],z[MX];
int cnt
[MX],C[MX],price
;
int f

[MX],from

[MX],last

[MX];

void Get(int l,int r,int p)
{
if(l>r) return;
int fr=from[l][r][p],la=last[l][r][p];
price[fr]=C[la];
Get(l,fr-1,la);Get(fr+1,r,la);
}

void Dp()
{
Rep(i,1,n) Rep(j,i,n) Rep(k,1,m) f[i][j][k]=-INF;
Rep(L,1,n) for(int l=1,r=l+L-1;r<=n;l++,r++)
{
Rep(k,l,r) Rep(i,1,m) cnt[k][i]=0;
Rep(i,1,m) if(a[i]>=l&&b[i]<=r) Rep(k,a[i],b[i]) cnt[k][c[i]]++;
Rep(k,l,r) Gep(i,m,1) cnt[k][i]+=cnt[k][i+1];
Rep(k,l,r) Rep(i,1,m){
if(f[l][k-1][i]+f[k+1][r][i]+C[i]*cnt[k][i]>f[l][r][i])
f[l][r][i]=f[l][k-1][i]+f[k+1][r][i]+C[i]*cnt[k][i],
from[l][r][i]=k,last[l][r][i]=i;
}
Gep(i,m,1) if(f[l][r][i]<f[l][r][i+1])
f[l][r][i]=f[l][r][i+1],from[l][r][i]=from[l][r][i+1],last[l][r][i]=last[l][r][i+1];
}
}

void work()
{
Dp();
printf("%d\n",f[1]
[1]);
Get(1,n,1);
Rep(i,1,n) printf("%d ",price[i]);
putchar('\n');
}

void init()
{
scanf("%d%d",&n,&m);
Rep(i,1,m) scanf("%d%d%d",&a[i],&b[i],&c[i]),z[i]=c[i];
sort(z+1,z+1+m);int M=unique(z+1,z+1+m)-z-1;
Rep(i,1,m){int x=lower_bound(z+1,z+1+M,c[i])-z;C[x]=c[i],c[i]=x;}
}

int main()
{
init();
work();
return 0;
}


a676
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: