HDU 1501 & POJ 2192 Zipper(dp记忆化搜索)

题意:给定三个串,问c串是否能由a,b串任意组合在一起组成,但注意a,b串任意组合需要保证a,b原串的顺序 例如ab,cd可组成acbd,但不能组成adcb。

分析:对字符串上的dp还是不敏感啊,虽然挺裸的....dp[i][j] 表示a串前i个,b串前j个字母能组成c串前i+j个字母。所以dp[lena-1][lenb-1] = 1; 就行了。

从后往前找就很好找了,从c串最后一个字符开始递归搜索。

 

#include <cstdio>

#include <iostream>

#include <cstring>

#include <cmath>

#include <algorithm>

# define MAX 222

using namespace std;



char a[MAX],b[MAX],c[MAX*2];

int dp[MAX][MAX];

int lena,lenb,lenc;



int dfs(int i,int j,int k) {

    //cout << i << ' ' << j << ' ' << k << endl;

    //cout << a[i] << ' ' <<  b[j] << ' ' << c[k]  << endl;

    if(dp[i][j] != -1 && i >=0 && j >=0) return dp[i][j];

    if(k == 0 && (a[i] == c[k] || b[j] == c[k])) return 1;

    if(i != -1 && a[i] == c[k]) {

        dp[i][j] = max(dp[i][j],dfs(i-1,j,k-1));

    }

    if(j != -1 && b[j] == c[k]) {

        dp[i][j] = max(dp[i][j],dfs(i,j-1,k-1));

    }

    if(dp[i][j] == -1)

        dp[i][j] = 0;

    return dp[i][j];

}



int main() {

    //freopen("D:\\in.txt","r",stdin);

    //freopen("D:\\out2.txt","w",stdout);

    int T;

    int casee = 1;

    cin >> T;

    while(T --) {

        memset(dp,-1,sizeof(dp));

        scanf("%s%s%s",a,b,c);

        printf("Data set %d: ",casee++);

        lena = strlen(a);

        lenb = strlen(b);

        lenc = strlen(c);

        //cout << lena << ' ' << lenb << ' ' << lenc << endl;

        if(lena + lenb != lenc) {

            puts("no");

            continue;

        }

        if(dfs(lena-1,lenb-1,lenc-1)) {

            puts("yes");

        }

        else puts("no");

    }

    return 0;

}


 


 

你可能感兴趣的:(zip)