您的位置:首页 > 其它

bzoj4380 Myjnie 动态规划

2016-03-28 20:14 375 查看
感谢Claris的题解

令t[l][r][x]表示l~r家店,最小的价格为x时,对于所有l<=a[i],b[i]<=r的顾客的最大收入;令f[l][r][x]表示最大收入时最小那家店的位置;同时令g[l][r][x]表示l~r家店,最小的价格>=x的最大收入,同时令pos[l][r][x]表示最小的价格的店。然后就是O(N^3M)了。

AC代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 55
#define M 4005
using namespace std;

int n,m,cnt,ans
,pos

[M],f

[M],g

[M],s
[M],a[M],b[M],c[M],num[M];
int find(int x){
int l=1,r=cnt,mid;
while (l<r){
mid=(l+r)>>1;
if (num[mid]<x) l=mid+1; else r=mid;
}
return l;
}
void solve(int l,int r,int k){
if (l>r) return;
int t=pos[l][r][k],mid=f[l][r][t];
ans[mid]=num[t]; solve(l,mid-1,t); solve(mid+1,r,t);
}
int main(){
scanf("%d%d",&n,&m); int i,j,k,x;
for (i=1; i<=m; i++){
scanf("%d%d%d",&a[i],&b[i],&c[i]);
num[i]=c[i];
}
sort(num+1,num+m+1);
cnt=1;
for (i=2; i<=m; i++)
if (num[i]!=num[cnt]) num[++cnt]=num[i];
for (i=1; i<=m; i++) c[i]=find(c[i]);
for (i=n; i; i--) for (j=i; j<=n; j++){
for (k=i; k<=j; k++) memset(s[k],0,sizeof(s[k]));
for (k=1; k<=m; k++) if (i<=a[k] && b[k]<=j)
for (x=a[k]; x<=b[k]; x++)
s[x][c[k]]++;
for (k=i; k<=j; k++)
for (x=cnt-1; x; x--) s[k][x]+=s[k][x+1];
for (x=cnt; x; x--){
int mx=0,tmp;
for (k=i; k<=j; k++){
tmp=g[i][k-1][x]+g[k+1][j][x]+s[k][x]*num[x];
if (tmp>=mx){
mx=tmp; f[i][j][x]=k;
}
}
if (mx>=g[i][j][x+1]){ g[i][j][x]=mx; pos[i][j][x]=x; }
else{ g[i][j][x]=g[i][j][x+1]; pos[i][j][x]=pos[i][j][x+1]; }
}
}
printf("%d\n",g[1]
[1]);
solve(1,n,1);
for (i=1; i<n; i++) printf("%d ",ans[i]);
printf("%d\n",ans
);
return 0;
}


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