HDU-1501 Zipper DFS+记忆化搜索

HDU-1501 Zipper DFS+记忆化搜索

    该题理解为将每一个字母与两个模式串进行匹配,如果不符合则回溯进行匹配。

一个例子:   aaabb  aaaaaacd aaaaaacaaabbd

到组合串第四个字母时,'a' 不能够与A串匹配,于是以状态为A:aaa__, B: a_______,组合串匹配到第五个字母进行递归,......当匹配到组合串的第七个字母 'c'时,该字母与A串以及B串的第四个字母均不能匹配,这时必定将回溯到组合串第三个'a'的匹配过程中,并将第三个 'a' 分配给B串,而这时,A串又会和组合串中的第四个'a' 匹配,接下来,又将以A:aaa__, B: a_______,组合串匹配到第五个字母进行递归过程。注意,这里就产生了跟前面相同的情况了,所以记忆化搜索便是剪枝的最佳方式。

    代码如下:

#include <stdio.h>
#include <string.h>
 
char  w1[205], w2[205], s[410];
 
int  flag1, flag2, len1, len2, lens, hash[205][205];
 
void  DFS( int  x, int  cnt1, int  cnt2 )
{
     if ( x== lens )
     {
         flag2= 1;
         return ;
     }
     if ( hash[cnt1][cnt2] )
     {
         return ;
     }
     hash[cnt1][cnt2]= 1;
     if ( s[x]== w1[cnt1] )
     {
         DFS( x+ 1, cnt1+ 1, cnt2 );
     }
     if ( s[x]== w2[cnt2] )
     {
         DFS( x+ 1, cnt1, cnt2+ 1 );
     }
}
 
int  main(  )
{
     int  T;
     scanf ( "%d" , &T );
     for ( int  t= 1; t<= T; ++t )
     {
         memset ( hash, 0, sizeof ( hash ) );
         flag1= flag2= 0;
         scanf ( "%s%s%s" , w1, w2, s );
         len1= strlen ( w1 );
         len2= strlen ( w2 );
         lens= strlen ( s );
         DFS( 0, 0, 0 );
         printf ( flag2== 1? "Data set %d: yes\n" : "Data set %d: no\n" , t );
     }
     return  0;
}
 
/*
3
cat tree tcraete
cat tree catrtee
cat tree cttaree
 
7
cat tree cttaree
Cat tree tCraete
vvv vvaa vvvaavv
abd hcda hcadbda
cat tree catrtee
bii iiii iiiibii
ddf fdd  fdddfd
*/
分类:  DFS-深度优先搜索,  记忆化搜索

Zipper

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 6840    Accepted Submission(s): 2465


Problem Description
Given three strings, you are to determine whether the third string can be formed by combining the characters in the first two strings. The first two strings can be mixed arbitrarily, but each must stay in its original order.

For example, consider forming "tcraete" from "cat" and "tree":

String A: cat
String B: tree
String C: tcraete


As you can see, we can form the third string by alternating characters from the two strings. As a second example, consider forming "catrtee" from "cat" and "tree":

String A: cat
String B: tree
String C: catrtee


Finally, notice that it is impossible to form "cttaree" from "cat" and "tree".
 

Input
The first line of input contains a single positive integer from 1 through 1000. It represents the number of data sets to follow. The processing for each data set is identical. The data sets appear on the following lines, one data set per line.

For each data set, the line of input consists of three strings, separated by a single space. All strings are composed of upper and lower case letters only. The length of the third string is always the sum of the lengths of the first two strings. The first two strings will have lengths between 1 and 200 characters, inclusive.

 

Output
For each data set, print:

Data set n: yes

if the third string can be formed from the first two, or

Data set n: no

if it cannot. Of course n should be replaced by the data set number. See the sample output below for an example.
 

Sample Input
           
           
           
           
3 cat tree tcraete cat tree catrtee cat tree cttaree
 

Sample Output
           
           
           
           
Data set 1: yes Data set 2: yes Data set 3: no
 

Source
Pacific Northwest 2004

DP解法:
最优子结构分析:如上例,如果A、B可以组成C,那么,C最后一个字母e,必定是 A 或 C 的最后一个字母组成。
C去除除最后一位,就变成是否可以求出 A-1和B 或者 A与B-1 与 是否可以构成 C-1。。。
状态转移方程: 用f[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]))


[cpp]  view plain copy
  1. #include<stdio.h>  
  2. #include<string.h>  
  3.   
  4. char a[201],b[201],c[402];  
  5. int la,lb,lc;  
  6. int dp[201][201];  
  7.   
  8. int main()  
  9. {  
  10.     int ncase;  
  11.     scanf("%d",&ncase);  
  12.     for(int n=1; n<=ncase; n++) {  
  13.   
  14.         a[0]='p';  
  15.         b[0]='p';  
  16.         c[0]='p';  
  17.   
  18.         scanf("%s%s%s",a+1,b+1,c+1);  
  19.   
  20.         la=strlen(a);  
  21.         lb=strlen(b);  
  22.         lc=strlen(c);  
  23.   
  24.         la-=1;  
  25.         lb-=1;  
  26.   
  27.         //处理边界  
  28.         for (int i=1; i<=la; i++)  
  29.             if (a[i]==c[i]) dp[i][0]=1;   
  30.   
  31.         for (int i=1; i<=lb; i++)  
  32.             if (b[i]==c[i]) dp[0][i]=1;  
  33.         //DP  
  34.         for (int i=1; i<=la; i++)  
  35.             for (int j=1; j<=lb; j++)  
  36.                 dp[i][j]= (dp[i-1][j]&&(a[i]==c[i+j]))||(dp[i][j-1]&&(b[j]==c[i+j]));  
  37.   
  38.         printf("Data set %d: ",n);  
  39.         if (dp[la][lb]==1) printf("yes\n");  
  40.         else printf("no\n");  
  41.     }  
  42.     return 0;  
  43. }  

你可能感兴趣的:(优化,字符串,递归,ACM,DFS)