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)

Description Given three strings, you are to determine whether the third string can be formed by com...
  • libin56842
  • libin56842
  • 2013年12月15日 19:37
  • 2323

poj 2192 Zipper(DFS+剪枝)

Zipper Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 16825   Accept...
  • CriminalCode
  • CriminalCode
  • 2015年07月07日 21:29
  • 337

poj 2192 DFS+剪枝

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

poj 2192 Zipper (DP)

#include #include #include #include #include #include #include #include #include #include ...
  • classicshao
  • classicshao
  • 2014年12月20日 13:40
  • 166

poj 2192 Zipper DP

dp[i][j]表示s1[]的前i个字符与s2[]的前j个字符能否成功组合,值分别为0,1 如果dp[i-1][j] == 1并且s1[i-1] == s3[i-1+j](s1,s2,s3都是从0开...
  • deng_yu
  • deng_yu
  • 2011年08月27日 18:28
  • 110

POJ 2192 Zipper (dp)

链接: http://poj.org/problem?id=2192  题意:就是给定三个字符串A,B,C;判断C能否由AB中的字符组成,同时这个组合后的字符顺序必须是A,B中原来的顺序,不能逆序;...
  • u012823258
  • u012823258
  • 2015年04月08日 14:54
  • 721

POJ - 2192 - Zipper (简单DP)

题目传送:Zipper 思路:设状态DP[i][j]为字符串A前i个字符和B前j个字符能否组成C的前i+j个字符,能则为true,否则false AC代码: #include #includ...
  • u014355480
  • u014355480
  • 2015年05月04日 00:07
  • 495

POJ 2192 Zipper简单dp

Zipper Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 17952 Acce...
  • Triose_Stream
  • Triose_Stream
  • 2016年07月23日 20:15
  • 156

POJ 2192 Zipper (DFS / DP)

开始DFS专题 做过, 记得 如果不剪枝不超时,就需要对 搜索过的进行标记,下次不再搜索; 最近看DP,就拿来看看,不过也是弄了一大会的。。。。。。 DFS代码 #include #includ...
  • u011065479
  • u011065479
  • 2013年07月23日 21:22
  • 687

hdu 1518 Square(dfs+剪枝)

Problem Description Given a set of sticks of various lengths, is it possible to join them end-to-en...
  • feizaoSYUACM
  • feizaoSYUACM
  • 2017年06月30日 10:47
  • 211
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:POJ 2192 Zipper [dfs+剪枝 || dp]
举报原因:
原因补充:

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