果然又废又很久没有打题,打坐半天可以的,效率0 。
题目:click
题意:
我们先来考虑题目。每个不同的区间,选择最小的且
<
=
C
[
i
]
<=C[i]
<=C[i],显然贪心的话不能够去确定最大的消费值,由可能最小值设定的小来洗车的人多或者加个大。考虑从dp入手,n个洗车店的价格每一个可以可以选择一个接着后头的,由于涉及到区间,可以设定成dp[i][j]:表示从i-j区间最大的花钱总和,由于每个区间需要一个最小值来计算价值确定,设dp[i][j][k]:区间i-j包含的所有区间,i-j区间中最小值为k,花钱最大。可以建立转移方程:
d
p
[
i
]
[
j
]
[
k
]
=
m
a
x
{
d
p
[
i
]
[
p
o
s
−
1
]
[
x
]
+
d
p
[
p
o
s
+
1
]
[
j
]
[
y
]
+
n
u
m
∗
k
}
。
x
,
y
≥
k
dp[i][j][k]=max\{dp[i][pos-1][x]+dp[pos+1][j][y]+num*k\}。x,y\geq k
dp[i][j][k]=max{dp[i][pos−1][x]+dp[pos+1][j][y]+num∗k}。x,y≥k,num表示包含完整区间经过pos的个数,他们就会选择第pos的洗车地方进行消费k元。由于x,y的位置不确定,可以把dp[i][j][k]定义为:区间i-j内最小值大于等于k的最大消费。通过pre[i][j][k]数组去确定大于等于k的最小值到底是多少,MAX[i][j][k]表示:最小值等于k的时候最大花费的位置是在i-j区间的哪个位置,逆推就可以转出转移路径输出答案。
#include<cmath>
#include<iostream>
#include<sstream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
//#include<unordered_map>
#include<map>
#include<algorithm>
#include<queue>
#define mmp make_pair
#define inf 0x3f3f3f3f
#define llinf 0x7fffffffffffffff
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PP;
typedef double ld;
int gcd(int a,int b) {
if(!b) return a;
else return gcd(b,a%b);
}
struct A {
int aa,bb,cc;
}a[4010];
int dp[55][55][4010],pre[55][55][4010];//pre记录最小的k值
int MAX[55][55][4010];// dp[i][j][x]//x>=k 的max的位置
int num[55][4010];//第i个洗车店 价格为j可以洗的数量
int ANS[55];
vector<ll>hh;
inline ll fiind(ll x) {
ll temp=lower_bound(hh.begin(),hh.end(),x)-hh.begin();
if(temp==hh.size())
return -1;
return temp+1;
}
void dfsans(int l,int r,int k) {
if(l>r) return ;
k=pre[l][r][k];
int pos=MAX[l][r][k];
ANS[pos]=hh[k-1];
dfsans(l,pos-1,k);
dfsans(pos+1,r,k);
}
int main() {
ios::sync_with_stdio(false);
int n,m;
scanf("%d %d",&n,&m);
for(int i=1;i<=m;++i) {
scanf("%d %d %d",&a[i].aa,&a[i].bb,&a[i].cc);
hh.push_back(a[i].cc);
}
sort(hh.begin(),hh.end());
hh.erase(unique(hh.begin(),hh.end()),hh.end());
for(int i=1;i<=m;++i) {
a[i].cc=fiind(a[i].cc);
}
memset(dp,0,sizeof(dp));
for(int i=n;i>0;--i) {
for(int j=i;j<=n;++j) {
for(int k=i;k<=j;++k) {
for(int l=0;l<=hh.size()+2;++l)
num[k][l]=0;
}
for(int k=1;k<=m;++k) {
if(i<=a[k].aa && j>=a[k].bb) {
for(int l=a[k].aa;l<=a[k].bb;++l)
++num[l][a[k].cc];
}
}
for(int k=i;k<=j;++k) {
for(int l=hh.size();l>0;--l) {
num[k][l]+=num[k][l+1];
}
}
for(int k=hh.size();k>0;--k) {
int maxn=0;
for(int pos=i;pos<=j;++pos) {
int w=dp[i][pos-1][k]+dp[pos+1][j][k]+num[pos][k]*hh[k-1];
if(maxn<=w) {
maxn=w; MAX[i][j][k]=pos;
}
}
if(maxn>=dp[i][j][k+1]) {
dp[i][j][k]=maxn;
pre[i][j][k]=k;
}
else {
dp[i][j][k]=dp[i][j][k+1];
pre[i][j][k]=pre[i][j][k+1];
}
}
}
}
printf("%d\n",dp[1][n][1]);
dfsans(1,n,1);
for(int i=1;i<=n;++i)
printf("%d ",ANS[i]);
return 0;
}