首页 > 其他分享 >洛谷P4158 [SCOI2009] 粉刷匠 题解

洛谷P4158 [SCOI2009] 粉刷匠 题解

时间:2023-10-10 16:22:40浏览次数:46  
标签:洛谷 int 题解 复杂度 char while const P4158 getchar

所有的 \(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

相关文章

  • 洛谷P3300 [SDOI2013] 城市规划 题解
    [SDOI2013]城市规划题意:给你一个\(6\timesn\)的网格题,单点修改,询问区间联通块数,\(n\le10^5\)。解:看起来就很显然的一道题......线段树每个点用一个ufs维护连通性;我为了方便思考把图转成横着的了。写起来真是毒瘤......重点在于:\(\bullet\)1、建立叶节点。\(\bull......
  • 【ABC320C】题解
    AtCoderBeginnerContest320ProblemC-SlotStrategy2(Easy)题解题目简述给定\(3\)个长度为\(m\)的转盘,转动过后三个转盘分别可以在不同的时间停下,求停下时所有转盘都显示相同数字的最小时间。思路由于这题\(m\le100\),数据较水,所以可以先把每个数列都复制\(......
  • 【ABC320D】题解
    AtCoderBeginnerContest320ProblemD-RelativePosition题解题目保证不矛盾,就可以直接vector建图,然后dfs一遍,边权为\((w_x,w_y)\)表示坐标的差,从\(u=1\)开始搜索,设点\(u,v\)有一条无向边,\(v_x=u_x+w_x,v_y=u_y+w_y\),最后如果没有被标记过的话(也就是没有......
  • 【题解】Fibonacci-ish II
    传送门题目分析根据题目范围\(n\le30000\)并且此题可以离线维护这个很恶心的东西,所以我们考虑莫队。由于要求访问到任意一个区间都要求知道它有序之后的序列,所以这个东西可以用权值线段树维护。因此,此题正解是莫队+权值线段树。我们分类讨论一下加上一个数,删除一个数对答案......
  • 题解 P3894【[GDOI2014] 传送】
    难倒不难,128MB的空间限制快恶心死我了。我们设\(d_{u_0,u_1}\)表示到节点\((u_0,u_1)\)距离最近的叶子的距离,这个可以很容易换根DP求出。设\(p_{u_0}\)表示树\(u_0\)中距离最近的两个叶子的距离。设\(dis(u_0,u_1,v_0,v_1)\)(\(u_0=v_0\))表示树中两个节点\(u_1\)和......
  • 【ABC322C】题解
    AtCoderBeginnerContest322ProblemC-Festival题解Meaning-题意简述给定\(N\)和\(M\),还有\(M\)个正整数\(a_1\sima_n\),对于每个\(i\len\),求出\(a\)中第一个大于等于\(i\)的整数和\(i\)的差。Solution-题解思路题目保证\(a\)数组单增,所以就可......
  • 【LG-P7617】题解
    题解思路不用关心每个数的每一位是什么、哪几位相同,我们只需记录每个数出现了哪几个数字,可以使用类似于状态压缩的思想记录每个数的状压形式,比如一个数为\((4)_{10}\),那么他的状态压缩形式为\((00001)_2\)。当两个数在状态压缩表示下有一位相同,我们就认为这两个数是一对,每个......
  • 【ABC322D】题解
    AtCoderBeginnerContest322ProblemD-Polyomino题解Meaning-题意简述给定三个字符矩阵,求它们能不能拼在一起变成一个\(4\times4\)的全部是#的矩阵。Solution-题解思路大模拟。说简单也不简单,很复杂;但是说难呢,又不难。思路:搜索每一个矩阵的状态。0x001旋......
  • P1220 关路灯 题解
    Description给定\(n\)个点的位置\(a_i\)和每秒的花费\(b_i\),你的初始位置是\(s\),你删掉一个点的时间为\(0\)秒,走\(1\)个单位长度的时间是\(1\)秒。请你确定一种关灯顺序,使得所有点的最终花费最小(删掉点后这个点不会再花费)。Solution每删掉一个点,有两种选择:继续往前......
  • 汉诺塔(河内塔)题解
    汉诺塔(河内塔)题解我们定义\(T_n\)为根据规则将\(n\)个圆盘从一根柱子移动到另一根柱子的最少移动步数,按照这样的定义,本道题的答案实际上就是\(T_n\)。通过手动模拟,可得到\(T_1=1,T_2=3\)。同时显然有\(T_0=0\),即表示\(0\)个圆盘根本无需做任何移动。接着我们开始考虑......