zoukankan      html  css  js  c++  java
  • HDU--杭电--1501--Zipper--深搜、DP都好

    Zipper

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


    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
     

    题意:输入三个字符串,前两个随意交错排列看能不能形成第三个

    思路:本题有缺陷,就是测试数据弱爆了,所以直接暴力深搜加几个特解就能过,不过暴力深搜的就没给代码了,直接是平常深搜的代码,然后是DP的代码,解释在代码中




    深搜:
    #include <iostream>
    #include <cstring>
    using namespace std;
    char s1[222],s2[222],s3[444];
    int l1,l2,visit[222][222];
    bool dfs(int i,int j,int k)
    {
        if(k==l1+l2)return 1;//s3的下标等于s1加s2长度的时候就表示搜完了
        if(visit[i][j])return 0;//这一步很重要,没了他就超时,深搜讲究的就是不重复搜同一个点
        visit[i][j]=1;
        if(i<l1&&s1[i]==s3[k]&&dfs(i+1,j,k+1))return 1;//s1能和s3匹配就递归一次,返回值为1就接着返回,因为返回1表示的就是找到了对的路了
        if(j<l2&&s2[j]==s3[k]&&dfs(i,j+1,k+1))return 1;//s2能和s3匹配也递归一次
        return 0;
    }
    int main (void)
    {
        int n,i,j,k=1;
        cin>>n;
        while(n--&&cin>>s1>>s2>>s3)
        {
            l1=strlen(s1);
            l2=strlen(s2);
            for(i=0;i<222;i++)//初始化标记数组
            for(j=0;j<222;j++)
            visit[i][j]=0;
            cout<<"Data set "<<k++<<": ";
            if(dfs(0,0,0))cout<<"yes"<<endl;//直接从三个字符串的第一个开始深搜
            else cout<<"no"<<endl;
        }
        return 0;
    }
    
    DP://DP的想法就是DP[i][j]代表s1[i]和s2[j]这两个点同ss[i+j]匹配的当前状态
    如匹配catrtee,不看其他杂乱的最终就得到这样个图(实际上还有些数字,因为可能是从中间开始匹配成功的)
        c a t
      0 1 2 0
    t 0 0 3 0
    r 0 0 4 5
    e 0 0 0 6
    e 0 0 0 7
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int l1,l2,l3;
    char s1[444],s2[444],ss[444];
    int main (void)
    {
        int i,j,n,m=1,dp[222][222];
        scanf("%d",&n);
        while(n--&&scanf("%s%s%s",s1,s2,ss))
        {
            memset(dp,0,sizeof(dp));
            l1=strlen(s1);
            l2=strlen(s2);
            l3=strlen(ss);
            if(ss[0]==s1[0])dp[1][0]=1;//如果s1第一个和ss配上就标记初始状态“s1成功一个,s2成功0个”为1
            if(ss[0]==s2[0])dp[0][1]=1;//同上
            for(i=0;i<=l1;i++)//有了初始状态之后就进行下面的递归
            for(j=0;j<=l2;j++)
            {
                if(i>0&&s1[i-1]==ss[i+j-1])//s1没完,就用s1来匹配
                dp[i][j]=max(dp[i][j],dp[i-1][j]+1);//取当前点的值与由前一个状态递推过来的值的最大值,因为有的从中间开始匹配成功的树值会干扰结果
                if(j>0&&s2[j-1]==ss[i+j-1])
                dp[i][j]=max(dp[i][j],dp[i][j-1]+1);
            }
            printf("Data set %d: ",m++);
            if(dp[l1][l2]==l3)
            cout<<"yes"<<endl;
            else cout<<"no"<<endl;
        }
        return 0;
    }
     



  • 相关阅读:
    leetcode刷题 650~
    leetcode刷题 633~
    发送udp报文
    SIP (Session Initiation Protocol) 协议
    你所不知道的replace
    uni-app(六)生成海报图片路径问题
    uni-app(五)小程序的一些注意事项,踩坑
    uni-app(四)小程序里的vuex
    uni-app(三)组件、插件使用,引入字体
    uni-app(二)接口请求封装,全局输出api
  • 原文地址:https://www.cnblogs.com/riasky/p/3476352.html
Copyright © 2011-2022 走看看