POJ 2192 Zipper [dfs+剪枝 || dp]

原创 2012年03月26日 17:43:47

题意:

给定三个字符串,如果前两个可以拼装成第三个,则输出yes,否则输出no。


思路:

1:

DFS:

最直观的思路是可以用dfs去搜,从第三个字符串为目标串去dfs(0,0,0)。

如果在第一个串里字符匹配,则dfs(i+1,j,k)。这种dfs本质所在搜一刻二叉树。

但是我觉得这种ac了说明数据弱,否则因为这种dfs需要回溯,很容易超时。

不过ac也是看了discuss里面的一个神奇的剪枝才ac的。


2:

DP:

从dfs深搜的过程中其实就可以发现规律。

我也是在写dfs的过程中想到其实可以用记忆化dp,因为记忆化搜索我的理解就是为了消除回溯的。

dp方程在代码里有解释。

时间复杂度O(N);


挺不错的一道题目,加深了我对记忆化dp的理解。


深搜代码:

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
const int N=405;
int len0,len1,len2;
char str[4][N];
int dp[N+N];
//dp[i+j]=(str1[i+1] && str2[j]) || (str1[])

bool dfs(int pt0,int pt1,int pt2)
{
	if(pt2>=len2)
	  return true;
	char a=str[2][pt2];
	//	printf("%d%d%d%c\n",pt0,pt1,pt2,a);
	//	printf("%c",str[0][pt0]);	
	if(pt0<len0&&str[0][pt0]==a)
	{
		if(dfs(pt0+1,pt1,pt2+1))
		  return true;
	}
	//	printf("%c",str[1][pt1]);	
	if(pt1<len1&&str[1][pt1]==a)
	{
		if(dfs(pt0,pt1+1,pt2+1))
		  return true;
	}
	//	printf("%d%d%d%c\n",pt0,pt1,pt2,a);
	return false;
}
void solve()
{
	if(dfs(0,0,0))
	  printf("yes\n");
	else
	  printf("no\n");
}
int main()
{
	//freopen("1.txt","r",stdin);
	int T;
	scanf("%d",&T);
	for(int t=1;t<=T;t++)
	{
		memset(dp,0,sizeof(dp));
		scanf("%s%s%s",str[0],str[1],str[2]);
		len2=strlen(str[2]);
		//		printf("%s %s %s\n",str[0],str[1],str[2]);
		len0=strlen(str[0]);
		len1=strlen(str[1]);
		if(str[0][len0-1]!=str[2][len2-1]&&str[1][len1-1]!=str[2][len2-1])
		{
			
			printf("Data set %d: no\n",t);
			continue;
		}
		printf("Data set %d: ",t);
		solve();
	}
	return 0;
}



dp代码:

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
const int N=405;
int len0,len1,len2;
char str[4][N];
bool dp[N][N/2];
//dp[k][i]:
//1:代表第三个字符串的第k个字符由第一个字符串的前i个字符和第二个字符从的前k-i个字符构成。
//0:代表第三个字符串的第k个字符由第一个字符串的前i个字符和第二个字符从的前k-i个字符无法构成。
bool solve()
{
	if(str[0][1]==str[2][1])
	  dp[1][1]=true;
	if(str[1][1]==str[2][1])
	  dp[1][0]=true;
	for(int k=1;k<len2;k++)
	{
		int flag=0;
		for(int i=0;i<=k;i++)
		{
			int j=k-i;
			if(dp[k][i])
			{
				flag=1;
				if(str[0][i+1]==str[2][k+1])
				{
					dp[k+1][i+1]=true;
				}
				if(str[1][j+1]==str[2][k+1])
				{
					dp[k+1][i]=true;
				}
			}
		}
		if(!flag)
		  return false;
	}

	bool ans=false;
	for(int i=0;i<len2;i++)
	{
		if(dp[len2][i])
		{
			ans=true;
			break;
		}
	}
	return ans;
}
int main()
{
	int T;
	scanf("%d",&T);
	for(int t=1;t<=T;t++)
	{
		memset(dp,0,sizeof(dp));
		scanf("%s%s%s",str[0]+1,str[1]+1,str[2]+1);
		len2=strlen(str[2]+1);
		len0=strlen(str[0]+1);
		len1=strlen(str[1]+1);
		printf("Data set %d: ",t);
		if(solve())
		  printf("yes\n");
		else
		  printf("no\n");
	}
	return 0;
}

人生第一次在linux下vim编辑器写的代码,用惯了vs 的人表示gdb调试得想哭,后来索性就放弃gdb了,直接靠printf来调试,泪流满面。



相关文章推荐

POJ2192 Zipper(DP||DFS)

题意: 输入三个字符串,看前两个字符串能否组成第三个字符串,要求前两个字符串各自的字母顺序在第三个字符串中保持不变 要点: 可以用dp或dfs做,下面是dp的思路: 首先用定义一个数组dp[i][j]...

HDU-1501 (POJ-2192) Zipper (DFS||DP)

要不是放在dp专题里面,我还一直以为只能dfs做 看到一个dp的解法,才明白如何进行状态转移 设dp[i][j]表示串a的前i个字符与串b的前j个字符是否能形成串c的前i+j个字符, 若dp[i-1...

YTU 2896/POJ 2192 Zipper dfs

2896: J--Zipper Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 25  Solved: 11 [Submit][Status][Web ...

POJ - 2192 - Zipper (简单DP)

题目传送:Zipper 思路:设状态DP[i][j]为字符串A前i个字符和B前j个字符能否组成C的前i+j个字符,能则为true,否则false AC代码: #include #includ...

POJ2192:Zipper(DP)

Description Given three strings, you are to determine whether the third string can be formed by com...

poj2192 Zipper(dp)

Zipper Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 17961 Accepte...

poj 2192 DFS+剪枝

题意:在不改变前两个字符串原始顺序的情况下,看能否组成第三个字符串。 思路:DFS+剪枝。递归三个字符串的下标,如果第三个字符串中的字符和前两个字符串中的字符有相等的,那么继续搜索,直到搜索到第一二...

poj2192(Zipper)

题目链接:http://poj.org/problem?id=2192          题意:给你三个字符串,问第三个字符串能否由前两个字符串按顺序组成(第三字符串的长度等于前两个字符串长度之和)...
  • kath_y
  • kath_y
  • 2012年06月08日 23:41
  • 383

POJ---2192-Zipper

A - Zipper Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit S...

POJ2192(Zipper)

DescriptionGiven three strings, you are to determine whether the third string can be formed by combi...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:POJ 2192 Zipper [dfs+剪枝 || dp]
举报原因:
原因补充:

(最多只允许输入30个字)