zoukankan      html  css  js  c++  java
  • 【56测试】【字符串】【dp】【记忆化搜索】【数论】

      第一题:神秘大门 大意:

      两个字符串A,B,按字典序最大的顺序输出B 的每个字符在A 中的位置,如果B不全在A中,输出No,否则Yes。

    解:

      这道题就是一遍的扫描,因为要按字典序最大的输出,所以从后面向前面扫描。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define maxn 1000005
     6 using namespace std;
     7 string s1,s2;
     8 int xi,yi,ans[maxn],head;
     9 int main()
    10 {
    11     freopen("door.in","r",stdin);
    12     freopen("door.out","w",stdout);
    13     cin>>s1;cin>>s2;
    14     xi=s1.size();yi=head=s2.size();
    15     if (xi!=0&&yi==0){
    16         cout<<"No"; 
    17         return 0;    
    18     } 
    19     while (yi!=0&&xi!=0)
    20     {
    21         if (s1[xi-1]==s2[yi-1]) {
    22             ans[yi]=xi;    
    23             yi--;
    24         }
    25         xi--;
    26     }
    27     if (xi==0&&yi!=0) {
    28         cout<<"No";
    29         return 0;
    30     }
    31     cout<<"Yes"<<endl;
    32     for (int i=1;i<=head;i++)
    33       printf("%d
    ",ans[i]);
    34     return 0;
    35 }

    第二题 集结蚂蚁 大意:

      给一个矩阵,1表示不通,0表示可走。奇数行是路径,偶数行的连续的0是蚁巢。从第一行开始往下走,问走到最后一行时经过的蚁巢的总大小。蚁巢的大小为连续的0的个数。如果不能到最后一行,则输出-1。

      样例:

      10 10
      1111101111
      1100001011    4
      1101111111
      1100000101    5
      1110110111
      1000110001    3
      1101111011
      1101000011    4
      1101011111
      1101010001    1

              17

    解:

      自己画完图后,想的是这道题肯定是动规 ,但是我还是用搜索吧。其实当时也想过用图做,把每一个蚁巢看做节点,然后把奇数行的路径看做边,把蚁巢的大小当做边的权值(如果有多个蚁巢,则取最大的),再搜一条最长路径就可以了。本以为是一棵树,但是觉得路径不一定只有一个0,可能有传递性,就又冒出来一个想法,可以对每一个蚁巢记录三个:bool in,out;表示有没有路径穿过它,否则这个蚁巢也没用;一个sum,记录走到这个蚁巢最大的ans大小。然后注意到当前蚁巢只会由上一个蚁巢推得,就用一个滚动数组。

      还有一个问题,就是判断能不能走到最后一行。先开始因为我用的滚动,所以相当于只判断了最后一行有没有连路径,但有可能这条路径不是与第一行联通的,所以 in 这个判断要从第一行向下传递,而不只是从上一行的路径传递下来。

      写动规的话,好像比我的代码少了好多行。。。。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<string>
     5 #include<algorithm>
     6 #define maxn 5005
     7 #define maxm 2005
     8 using namespace std;
     9 struct pp{
    10     bool in,out;
    11     int sum;
    12 }; 
    13 pp ant_home[5][maxm];
    14 bool isroad[maxm];
    15 int n,m,cnt,road[maxm],home[maxm],cur=1,suf,last_cnt,ans;
    16 char c[maxm];
    17 void clr_suf()
    18 {
    19     //cnt=0;
    20     for(int i=1;i<=last_cnt;i++)
    21     {
    22         ant_home[suf][i].in=false;
    23         ant_home[suf][i].out=false;
    24         ant_home[suf][i].sum=0;
    25     }
    26 }
    27 void worki()//处理路径 
    28 {
    29     memset(road,0,sizeof(road));
    30     memset(isroad,0,sizeof(isroad));
    31     for (int i=1;i<=m;i++)//更新可走蚁巢和标记 
    32     if (c[i]=='0'){
    33         isroad[i]=true;
    34         if (home[i]!=0){//上一行 
    35             road[i]=home[i];
    36             ant_home[suf][home[i]].out=true;
    37         }
    38         int st=i;
    39         while(c[st]=='0'){//它相连的左边的路 更新 
    40             if (road[st]){
    41                 if (!road[i]) road[i]=road[st];
    42                 else{
    43                     if (ant_home[suf][road[st]].sum>ant_home[suf][road[i]].sum)
    44                      road[i]=road[st];
    45                     else road[st]=road[i];
    46                 }
    47             }else if (road[i]) road[st]=road[i];
    48             st--;
    49         }
    50     }
    51 }
    52 void workj()//处理蚁巢 
    53 {
    54     int i=1;
    55     memset(home,0,sizeof(home));
    56     while (i<=m){
    57         if (c[i]=='0') {
    58             int st=i;
    59             cnt++;
    60             while (c[i]=='0') {
    61                 if(isroad[i]) {
    62                     ant_home[cur][cnt].in=true;
    63                     int _last=road[i];
    64                     if (ant_home[suf][_last].in&&ant_home[suf][_last].out)
    65                       ant_home[cur][cnt].sum=max(ant_home[cur][cnt].sum,ant_home[suf][_last].sum);
    66                 }
    67                 home[i]=cnt;
    68                 i++;
    69             }
    70             ant_home[cur][cnt].sum+=i-st;
    71         }
    72         else i++;
    73     }
    74     clr_suf();//滚动数组清零 
    75     last_cnt=cnt;
    76     cnt=0;
    77     swap(cur,suf);
    78 }
    79 int main()
    80 {
    81     freopen("ant.in","r",stdin);
    82     freopen("ant.out","w",stdout);
    83     scanf("%d%d",&n,&m);
    84     for (int i=1;i<=n;i++)
    85     {
    86         scanf("%s",c+1);
    87         if (i%2) worki();
    88         else workj();  
    89     }
    90     swap(cur,suf);//******
    91     for (int i=1;i<=last_cnt;i++)
    92       if(ant_home[cur][i].in&&ant_home[cur][i].sum>ans) 
    93               ans=ant_home[cur][i].sum;
    94     if(ans) cout<<ans;
    95     else cout<<-1;
    96     return 0;
    97 }

    第三题 计数 大意:

      长n宽m的矩阵点之间连线,问长度为 wi 的线有多少条。

    解:

      做到这道题,已经只有半个小时了,又没有把题读清楚,以为只有横边 和竖边,觉得好简单,到最后才发现,还有斜边,已经没有时间了。

      然后,这道题的正解是数论,各种转换,我也还没弄懂,就先不写了,昨天把脚扭了,现在还痛的不行。

      

  • 相关阅读:
    postman的使用方法详解!最全面的教程
    免费使用的加速器
    Windows添加启动项的两种方法
    Python版本微信跳一跳,软件配置
    Inno Setup教程
    Go开发环境安装配置
    Linux下安装Phantomjs
    Python的url解析库--urlparse
    Python处理HTML转义字符
    Python使用base64编码的问题
  • 原文地址:https://www.cnblogs.com/lx0319/p/6025913.html
Copyright © 2011-2022 走看看