因为每个人不洗车的条件是最小价格大于c[i],所以易知最后每家店的价格都是c[i]一定有一种方案使得所有人花的钱总和最大
那么就和c[i]的具体数值无关,先把它离散化
然后因为一个人决策的标准和区间的最小值有关,将c[i]引入状态定义,
定义f[i][j][c]代表
i∽j
的最小值为
c
,这个区间包含的人花的钱最多是多少,枚举左端点DP
于是枚举
那么写出方程
f[i][j][c]=max(max(f[i][k−1][c2],c2>=c)+max(f[i][k+1][c3],c3>=c)+c∗h[k][c])
发现仍然不太好转移,所以还要维护一个 g[i][j][c] 表示 max(f[i][j][k],k>=c)
维护了这三个后就可以DP求解了
答案就是 g[1][n][1] ,然后要求输出方案,可以在转移的时候记录每个 f <script type="math/tex" id="MathJax-Element-13">f</script>是哪个位置取了c值,搜一下就好了
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
inline void up(int &x,const int &y){if(x<y)x=y;}
const int maxn = 55;
const int maxm = 4100;
const int maxc = 510000;
struct node
{
int a,b,c;
}a[maxm];
inline bool cmp(node x,node y){return x.b==y.b?x.a<y.a:x.b<y.b;}
int f[maxn][maxn][maxm],g[maxn][maxn][maxm],h[maxn][maxm];
int p[maxn][maxn][maxm],val[maxn];
int C[maxm],lsh[maxc],LSH[maxm],K;
int n,m;
void pre()
{
sort(a+1,a+m+1,cmp);
sort(C+1,C+m+1); K=0;
for(int i=1;i<=m;i++)
if(C[i]!=C[i-1]) LSH[++K]=C[i],lsh[C[i]]=K;
for(int i=1;i<=m;i++) a[i].c=lsh[a[i].c];
}
void search(int l,int r,int k)
{
if(l>r) return ;
if(!g[l][r][k])
{
for(int i=l;i<=r;i++) val[i]=LSH[k];
return ;
}
for(int i=k;i<=K;i++) if(g[l][r][k]==f[l][r][i])
{
const int pos=p[l][r][i];
val[pos]=LSH[i];
search(l,pos-1,i); search(pos+1,r,i);
break;
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&a[i].a,&a[i].b,&a[i].c),C[i]=a[i].c;
pre();
for(int l=n;l>=1;l--) for(int r=l;r<=n;r++)
{
for(int i=l;i<=r;i++) for(int j=1;j<=K;j++) h[i][j]=0;
for(int i=1;i<=m&&a[i].b<=r;i++)
{
if(a[i].a<l) continue;
for(int j=a[i].a;j<=a[i].b;j++) h[j][a[i].c]++;
}
for(int i=l;i<=r;i++) for(int j=K-1;j>=1;j--) h[i][j]+=h[i][j+1];
for(int i=l;i<=r;i++)
{
for(int j=K;j>=1;j--)
{
int tmp=g[l][i-1][j]+g[i+1][r][j]+h[i][j]*LSH[j];
if(f[l][r][j]<tmp) f[l][r][j]=tmp,p[l][r][j]=i;
g[l][r][j]=g[l][r][j+1]>f[l][r][j]?g[l][r][j+1]:f[l][r][j];
}
}
}
printf("%d\n",g[1][n][1]);
search(1,n,1);
for(int i=1;i<=n;i++) printf("%d ",val[i]);
return 0;
}