首页 > 代码库 > uva 1625 - Color Length(dp 里面 L C S 问题解决方式变形)
uva 1625 - Color Length(dp 里面 L C S 问题解决方式变形)
LCS属线性结构上的动态规划,应该是动规里面很简单的一种类型。
最长公共子序列问题,一旦明确了状态,找到状态转移方程还是很简单的。但是对于本题来说,难点之一就是会很难想到该如何定义状态。
作为一只菜鸟,兹认为此题很复杂。
首先我是想不到每一步都把没到终点的字母全加上1,以及这种效果与你去找开始和结束的效果是一样的。
甚至,若不是在做动规的专题,我根本想不到这样的题目,会用动规来解决。
再一个,我想不到状态可以这么来定义“设d[ i ][ j ]表示两个序列分别已经拿出去了 i 个和 j 个元素 ”。其值代表的是当前状态的最小L值。
再一个我很难相信自己能完成前期对cnt[ i ][ j ]数组的处理,事实上我已经完成了其大半,但是因为对自己的好像是O(n^3)方法没有信心,怯懦的放弃了。
再一个不知道是不是因为对复杂处理的恐惧,在明确了方法之后,写代码的过程中也一直没有清楚的思路,导致在解题过程中很多地方没有处理好,对最后结果造成了巨大的影响,也为最后的debug造成了极大困难,浪费了很多的精力和时间,做了很多的无用功,必须好好反思。
最后虽然明确了状态转移方程,但是在对边界的处理上,思路可谓混乱不堪。简直是在猜测!问问自己这是什么状态?你该猜吗?你连脑子都不转你既然猜那你怎么不去搬砖,你猜个P啊?你就不能静下心来人认真考虑考虑便捷的状态吗?我觉得你肯定能把边界标示清楚,你为什么不肯静下来好好思考思考?必须反思!
环境太乱影响了我,周围的讨论使我浮躁。但是不该对任何一道题目浮躁。
#include<cstdio> #include<string> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define INF 0x6fffffff const int maxn = 5010; char s1[maxn],s2[maxn]; struct color { int st1,end1; int st2,end2; int ok; }co[30]; int cnt[maxn][maxn]; int d[maxn][maxn]; int main() { int t; scanf("%d",&t); while(t--) { scanf("%s%s",s1,s2); int len1 = strlen(s1); int len2 = strlen(s2); for(int i=0;i<30;i++) { co[i].ok=1; co[i].st1=co[i].st2=INF; co[i].end1=co[i].end2=-INF; } for(int i=0;i<len1;i++) { int temp = s1[i]-'A'; if(co[temp].ok==1) { co[temp].ok=0; co[temp].st1=i; } co[temp].end1=i; } for(int i=0;i<30;i++) { co[i].ok=1; } for(int i=0;i<len2;i++) { int temp = s2[i]-'A'; if(co[temp].ok==1) { co[temp].ok=0; co[temp].st2=i; } co[temp].end2=i; } for(int i=0;i<=len1;i++) { for(int j=0;j<=len2;j++) { int cnt_=0; for(int k=0;k<26;k++) { if(co[k].st1==INF&&co[k].st2==INF) continue; if(co[k].st1>i-1&&co[k].st2>j-1)///注意是i-1;(已推理验证,正确) continue; if(co[k].end1<=i-1&&co[k].end2<=j-1)///是小于等于i-1;(已验证,正确) continue; cnt_++; } cnt[i][j]=cnt_; } } d[len1][len2]=0; for(int i=len2-1;i>=0;i--) { d[len1][i]=d[len1][i+1]+cnt[len1][i]; } for(int i=len1-1;i>=0;i--) { d[i][len2]=d[i+1][len2]+cnt[i][len2]; } for(int i=len1-1;i>=0;i--) { for(int j=len2-1;j>=0;j--) { d[i][j]=min(d[i+1][j],d[i][j+1])+cnt[i][j]; } } printf("%d\n",d[0][0]); } return 0; }
以后递推过程中再不用len1,len2,骂了隔壁看着就不爽艹!!!!!不爽 !艹!!!!
做题很久了,该静下心,遇到复杂的题目和解决不了的题目也该有自己的态度。烦躁解决不了任何事情,也不会有任何帮助。发泄归发泄,认真对待是最重要的
宁肯不做,也不凑过。
再一个,适当提高对自己能力的肯定,既然有想法与思路,就鼓励自己一定要写完看看~即使超时是不正确,也是对自己代码能力和心智的一种锻炼,有助于代码能力的提高,也有助于增强自己面对复杂题目敢于下手的信念。不怕麻烦,不惧困难。缺少一种 就是干 的精神