所有的 \(DP\) ,只要式子一推出来(不管复杂度),那就很简单了,因为优化是成千上万种的……
思路1:
我们考虑设 \(f[i][j][k]\) 表示:当前 \(DP\) 到第 \(i\) 块木板的第 \(j\) 个位置,共涂了 \(k\) 次,所能获得的最大收益。因为还要枚举当前这次涂是从哪到哪的,因此复杂度为 \(O(NM^2T)\) ,实际 \(90\%\) 。在实际操作中,第一维可以省略。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=110;
const int M=5e3+100;
int n,m,t,ans;
int f[N][M],res[N][N][2];
char s[N];
inline int read(){
char c=getchar();int f=1,x=0;
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
int main(){
n=read();
m=read();
t=read();
for(int l=1;l<=n;l++){
scanf("%s",s+1);
for(int i=1;i<=m;i++){
for(int j=i;j<=m;j++){
res[i][j][0]=res[i][j-1][0]+(s[j]=='0');
res[i][j][1]=res[i][j-1][1]+(s[j]=='1');
}
}
for(int i=0;i<=t;i++) f[0][i]=f[m][i];
for(int i=1;i<=m;i++){
for(int j=1;j<=t;j++){
f[i][j]=0;
for(int k=0;k<i;k++) f[i][j]=max(f[i][j],f[k][j-1]+max(res[k+1][i][0],res[k+1][i][1]));
}
}
}
for(int i=1;i<=t;i++) ans=max(ans,f[m][i]);
printf("%d\n",ans);
return 0;
}
虽然开个 \(O_2\) 甚至只是单纯卡卡长也一样能过,但是介于十年前评测姬的蜜汁速度,我们思考还有没有优化复杂度的余地。
思路2:
我们考虑设 \(f[i][j][k][0/1/2]\) 表示:
当前 \(DP\) 到第 \(i\) 块木板的第 \(j\) 个位置,共涂了 \(k\) 次,当前这个位置的状态是 \(0/1/2\) 。
其中,状态 \(0\) 意为涂上了颜色 \(0\) ,状态 \(1\) 意为涂上了颜色 \(1\) ,状态 \(2\) 意为啥也没涂。
因为这种方法不需要枚举上一次的断点,因此复杂度是 \(O(NMT)\) 的。老样子,第一维可以砍掉。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=110;
const int M=5e3+100;
int n,m,t,ans;
int f[N][M][3];
char s[N];
inline int read(){
char c=getchar();int f=1,x=0;
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
int main(){
n=read();
m=read();
t=read();
for(int l=1;l<=n;l++){
scanf("%s",s+1);
for(int i=0;i<=t;i++) f[0][i][2]=max(max(f[m][i][0],f[m][i][1]),f[m][i][2]);
for(int i=1;i<=m;i++){
for(int j=1;j<=t;j++){
f[i][j][2]=max(max(f[i-1][j][0],f[i-1][j][1]),f[i-1][j][2]);
f[i][j][1]=max(max(f[i-1][j-1][0],f[i-1][j][1]),f[i-1][j-1][2])+(s[i]=='0');
f[i][j][0]=max(max(f[i-1][j][0],f[i-1][j-1][1]),f[i-1][j-1][2])+(s[i]=='1');
}
}
}
for(int i=1;i<=t;i++) ans=max(max(ans,f[m][i][0]),max(f[m][i][1],f[m][i][2]));
printf("%d\n",ans);
return 0;
}
标签:洛谷,int,题解,复杂度,char,while,const,P4158,getchar
From: https://www.cnblogs.com/xuantianhao/p/17754996.html