FOJ有獎月賽-2015年03月

弱爆了,細節處理不了,代碼熟練度也不行大哭,想法有時候還過於複雜,整個人都需要被優化。


A簡單題

沒有什麼算法字符串代碼題。

但是複習了不少關於字符串處理的知識。

題意:給你兩個串,一個模式串A,一個匹配串B,找B是否在A裏。

模式串A比較特殊acb[3]d[5]e,是被壓縮後的數字代表的是壓縮的個數

例:acb[3]d[5]e   acbbbddddde(比較坑的點在於他可能不是完全壓縮的,在處理的時候還要再壓縮一次)

這是學長給我指出來的,善良的孩子總是被惡意欺騙哭

輸入:acb[3]d[5]e

           bd

輸出:True(沒有是False)

想法:把一個串完全壓縮,第二串也完全壓縮,比較的時候按照字符串匹配(BF)查找即可,當然也可以用(KMP),這裏要注意的是,除了要匹配字符串,還要比較數目的大小,要保證B串壓縮的數要小於等於A串同一個數。

我的錯誤的代碼(以後注意每一步,都要把運行的結果很好的輸出來,以便差錯):

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define maxn 1003
struct tt
{
    char c;
    int n;
};
int main()
{
   // char tt[maxn];///臨時串
   char t[maxn];
    char ss[maxn];///輸入的臨時串
    char ns[maxn];///用來被比較的串
    tt s[maxn],n_s[maxn];///用來處理分析的串
    while(~scanf("%s",ss))
    {
        scanf("%s",ns);
        int count=-1;///第一個模式串的計數器
        int len_ss=strlen(ss);///模式串的長度
        int len_ns=strlen(ns);///匹配串的長度
        for(int i=0;i<len_ss;i++)
        {
            if(ss[i]>='a'&&ss[i]<='z'){
                s[++count].c=ss[i];///處理第一個串
                s[count].n=1;
            }
            if(ss[i]=='[')///統計數,超過1位的整數
            {
                int sum=0;
                int j=0;
                int k=i;
                i++;
                while(ss[i]!=']')
                {
                    t[j++]=ss[i];
                    i++;
                }
                sscanf(t,"%d",&sum);
                s[count].n=sum;
            //    cout<<sum<<"*"<<endl;
            }

        }
        int len_1=count+1;
        count=-1;
       // cout<<ns<<endl;
        int cnt=1;
        for(int i=0;i<len_ns;i++)
        {///匹配串的長度

            if(ns[i]!=ns[i+1]){
                n_s[++count].c=ns[i];
                n_s[count].n=cnt;
                cnt=1;
            }
            else cnt++;
        }
        int len_2=count+1;
      /*  for(int i=0;i<len_1;i++)///輸出的測試表
            cout<<s[i].c<<" "<<s[i].n<<endl;
            for(int i=0;i<len_2;i++)
            cout<<n_s[i].c<<" "<<n_s[i].n<<endl;*/
        int i=0,j=0,flag=0;
        while(i<len_1&&j<len_2)///串的匹配
        {
            if(s[i].c==n_s[j].c&&s[i].n>=n_s[j].n)
            {
             cout<<s[i].c<<" "<<n_s[j].c<<endl;
                i++;
                j++;
            }
            else{
                i=i-j+1;
                j=0;
            }
            if(j>=len_2)
                flag=1;
        }
        if(flag==1)///輸出結果
            cout<<"True"<<endl;
        else
            cout<<"False"<<endl;

       // cout<<count+1<<endl;
       // ss[count++]='\0';



    }
    return 0;
}
正確的代碼:

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
#include <cmath>
#include <iomanip>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cctype>
#define rd(x) scanf("%d",&x)
#define rd2(x,y)  scanf("%d%d",&x,&y)
#define rd3(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
ll has1[1011];
ll has11[1011];
ll has2[1011];

string s1;
string s2;
string s11;
string tp;
string tp2;

void change()
{
    //瘦身s1
    int len1=tp2.length();
    s1="";
     int pos=0;
    for(int i=0;i<len1;i++)
    {
        ll num=1;
        if(isalpha(tp2[i]))
        {
            s1.push_back(tp2[i]);
            if(i+1<len1&&tp2[i+1]=='[')//左括號的位置
            {
                num=0;
                int r=i+2;
                while(tp2[r]!=']')
                    {
                        num=num*10+tp2[r]-'0';
                        r++;
                    }
                i=r;
            }
            has1[pos++]=num;
        }
    }

    //s1去重,比如aacccdfe這種的
    pos=0;
    s11="";
    len1=s1.length();
    for(int i=0;i<len1;i++)
    {
        int r=i+1;
        ll cnt=has1[i];
        s11.push_back(s1[i]);
        while(s1[r]==s1[i])
        {
            cnt+=has1[r];
            r++;
        }
        has11[pos++]=cnt;
        if(r==i+1)
            continue;
        i=r-1;
    }

    int len=tp.length();
    s2="";
    pos=0;
    for(int i=0;i<len;i++)
    {
        int cnt=1;
        for(int p=i+1;p<len;p++)
        {
            if(tp[p]==tp[p-1])
                cnt++;
            else
                break;
        }
        if(cnt==1)
            {
                s2.push_back(tp[i]);
               // pos++;
                has2[pos++]=1;
            }
        else
        {
            s2.push_back(tp[i]);
            has2[pos++]=cnt;
            i=i+cnt-1;
        }
    }
}

bool work()
{
    int len1=s11.length();
    int len2=s2.length();
    /*
    cout<<"s11 "<<s11<<endl;
    for(int i=0;i<s11.length();i++)
        cout<<has11[i]<<" ";
    cout<<endl;
    cout<<"s22 "<<s2<<endl;
    for(int i=0;i<s2.length();i++)
        cout<<has2[i]<<" ";
    cout<<endl;*/
    for(int i=0;i<len1;i++)
    {
        int p1=i;
        int p2=0;
        if(s11[p1]!=s2[p2])
            continue;
        //首先第一個字母
        if(has11[p1]<has2[p2])
            continue;
        if(has11[p1+len2-1]<has2[len2-1])
            continue;
        if(len2==1||len2==2)
            return true;
        p1++;
        p2++;
        while(p2<len2-1)
        {
            if(s11[p1]!=s2[p2])
                break;
            if(has11[p1]!=has2[p2])
                break;
            p1++;
            p2++;
        }
        if(p2==len2-1)
            return true;
    }
    return false;
}

int main()
{
    while(cin>>tp2>>tp)
    {
        memset(has1,0,sizeof(has1));
        memset(has2,0,sizeof(has2));
        memset(has11,0,sizeof(has11));
        change();
        if(work())
            printf("True\n");
        else
            printf("False\n");
    }
    return 0;
}

唉,就是跟我這種小菜鳥的感覺,不一樣。

B、逆序數還原

應該被秒A的題,我還是做了很長時間。還因爲沒有換行而導致PE了一次。

題意:給出N,表示數組的個數,再給出一個狀態數組,該數組表示該數後面有幾個比他小的數。

讓你還原數組,輸出。

例:2 0 1 0 0

       3 1 4 2 5

注意的是題目中沒有明確指明,數一定是從1到n的。

輸入:5

           2 0 1 0 0

輸出:3 1 4 2 5

想法:在未選擇的序列排的序號就是給出的狀態號。比如假設1 2 3 4 5,如果排序爲3 1  4 2 5,那麼比3小得一定有兩個,到1的時候,如果說狀態號爲0的號,即是排第一的數,當然之前選擇過得數要被摘出去。

代碼:

#include <iostream>
#include <cstdio>
using namespace std;
#define maxn 1002
int t[maxn],now[maxn];
int main()
{
    int n,tt;
    while(~scanf("%d",&n))
    {
         for(int i=0;i<n;i++)///初始化,全部爲1標記
            t[i]=1;
        for(int i=0;i<n;i++)
        {
            int count=-1;
            scanf("%d",&tt);///tt表示後面有幾個比他大的數
            for(int j=0;j<n;j++)
            {
                if(t[j]==1)
                   count++;
                if(count==tt)
                {
                    now[i]=j+1;
                    t[j]=0;
                    break;
                }
            }
        }
        printf("%d",now[0]);
        for(int i=1;i<n;i++)
            printf(" %d",now[i]);
        printf("\n");
    }
    return 0;
}
後面都沒做出來,因爲有些事沒能堅持做到最後。。。。。。

3、數的路徑覆蓋

4、小明的迷宮

剛看到這道題的時候,想到是搜索,但是同學說會超時,要用狀態壓縮dp,已經完全忘記了有沒有抓狂

5、回家種地

6、迷宮I

7、迷宮II

坐等各位大神的題解出來然後我再來補充不懂知識點啊可憐



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章