hdu1501 zipper【记忆化搜索】【动态规划】
2017-10-11 20:37
411 查看
题目大意:
给三个字符串A,B,C,问A和B能否按顺序组成C;解题思路:
冲突关键在于如果C中某字符刚好都等于枚举到的A中字符和B中字符该怎么转移。法一:记忆化搜索。
dp[i][j]表示A枚举到i,B枚举到j时能否匹配成功。
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<cmath> #include<queue> #include<vector> #define ll long long using namespace std; int getint() { int i=0,f=1;char c; for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar()); if(c=='-')c=getchar(),f=-1; for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0'; return i*f; } const int N=205; int T,t1n,t2n,sn,dp ; char t1 ,t2 ,s[N<<1]; bool dfs(int x,int y,int z) { if(x==t1n+1&&y==t2n+1&&z==sn+1)return true; if(dp[x][y]!=-1)return dp[x][y]; if(s[z]==t1[x]&&s[z]==t2[y])return dp[x][y]=dfs(x+1,y,z+1)||dfs(x,y+1,z+1); else if(s[z]==t1[x])return dp[x][y]=dfs(x+1,y,z+1); else if(s[z]==t2[y])return dp[x][y]=dfs(x,y+1,z+1); return dp[x][y]=false; } int main() { //freopen("lx.in","r",stdin); T=getint(); for(int k=1;k<=T;k++) { memset(dp,-1,sizeof(dp)); scanf("%s%s%s",t1+1,t2+1,s+1); t1n=strlen(t1+1); t2n=strlen(t2+1); sn=strlen(s+1); printf("Data set %d: ",k); if(!dfs(1,1,1))puts("no"); else puts("yes"); } return 0; }
法二:动态规划。
最优子结构分析:如果A、B可以组成C,那么C最后一个字母必定是 A 或 C 的最后一个字母组成。
C去除除最后一位,就变成是否可以求出 A-1和B 或者 A与B-1 与 是否可以构成 C-1。。。
状态转移方程: 用dp[i][j] 表示 表示A前 i 为 和B 前j 位是否可以组成 C的前i+j位
dp[i][j]= (dp[i-1][j]&&(a[i]==c[i+j]))||(dp[i][j-1]&&(b[j]==c[i+j]))
注意对边界的处理,初始化条件为主串长度的字符相同即为1,否则为0。
就是转移方程中i=0或j=0的情况,但i-1=-1会炸。
其意义是为判断整个A或B是C的前缀。
#include <stdio.h> #include <algorithm> #include <string.h> #include <string> #include <iostream> using namespace std; const int N = 205; const int INF = 1e8; char str1 , str2 , str[N * 2]; int dp ; int main() { int t, n, Case = 1; scanf("%d", &t); while(t --) { scanf("%s%s%s", str1 + 1, str2 + 1, str + 1); str[0] = str1[0] = str2[0] = '0'; // memset(dp, 0, sizeof(dp)); for(int i = 1; i < strlen(str1); i ++) { if(str1[i] == str[i]) dp[i][0] = 1; else dp[i][0] = 0; } for(int i = 1; i < strlen(str2); i ++) { if(str2[i] == str[i]) dp[0][i] = 1; else dp[0][i] = 0; } for(int i = 1; i < strlen(str1); i ++) { for(int j = 1; j < strlen(str2); j ++) { dp[i][j] = ((dp[i - 1][j] && str1[i] == str[i + j]) || (dp[i][j - 1] && str2[j] == str[i + j])); } } if(dp[strlen(str1) - 1][strlen(str2) - 1]) printf("Data set %d: yes\n", Case ++); else printf("Data set %d: no\n", Case ++); } return 0; }
相关文章推荐
- hdu 1501 Zipper(记忆化搜索)
- 【记忆化搜索】HDU-1501 Zipper
- POJ 2192 && HDU 1501 Zipper (记忆化搜索)
- HDU 1501 Zipper(Dfs记忆化搜索)
- HDU1501 Zipper(DFS+记忆化搜索)
- hdu 1501 Zipper 记忆化搜索
- hdu 1501 Zipper (dfs+记忆化搜索)
- HDU 1501 Zipper 动态规划经典
- HDU 1501 Zipper 动态规划经典
- hdu 1501 Zipper
- hdu 1501 Zipper
- HDU 1501 Zipper(dfs)
- HDU 1501 Zipper(dp)
- HDU 1501 Zipper & ACM俱乐部 2604 单词混合【记忆化搜索】
- HDU 1501 Zipper 记忆化搜索
- HDU 1501 Zipper【DP】
- HDU 1501 Zipper(DFS)
- HDU 1501 Zipper 【DFS+剪枝】
- HDU 1501 Zipper
- Hdu 1501 Zipper