【6.12校內test】T1單詞序列

【問題描述】node

       給出兩個單詞(開始單詞和結束單詞)以及一個詞典。找出從開始單詞轉換到結束單詞, 所須要的最短轉換序列。轉換的規則以下:ios

一、每次只能改變一個字母c++

二、轉換過程當中出現的單詞(除開始單詞和結束單詞)必須存在於詞典中算法

例如: 開始單詞爲:hit數組

結束單詞爲:cog函數

詞典爲:[hot,dot,dog,lot,log,mot]spa

那麼一種可能的最短變換是: hit -> hot -> dot -> dog -> cog,code

因此返回的結果是序列的長度 5;blog

注意: 一、若是不能找到這種變換,則輸出 0;ci

二、詞典中全部單詞長度同樣;

三、全部的單詞都由小寫字母構成;

四、開始單詞和結束單詞能夠不在詞典中。

【輸入文件】

         共兩行,第一行爲開始單詞和結束單詞(兩個單詞不一樣),以空格分開。第二行爲若干 的單詞(各不相同),以空格分隔開來,表示詞典。單詞長度不超過 5,單詞個數不超過 30。

【輸出文件】

       輸出轉換序列的長度。

【輸入樣例】

hit cog

hot dot dog lot log

【輸出樣例】

5

【數據範圍】

單詞長度不超過5,單詞個數不超過30;


這個題算法大概是搜索,這可真的是使人質壁分離。

還記得我烤雞寫了一個多小時呀qwq(果然仍是我太菜了),感受本身代碼能力真心很差呀,我可能也就for寫的足夠優秀了emmm。

(滾去寫這個題代碼了)

MY SOLUYION:
first.這個題讀入就很卡人,下面咱們來總結一下輸入若干個(題目未給出具體的數值)應該腫麼寫:

  1. 輸入一串長度不定的字符串
    string a;
    cin>>a;//直接用string而後cin或scanf輸入就好;
  2. 今天用到的(個人寫法)(自我感受良好)
    while(ch!='\n'){
            n++;
            scanf("%s",dic[n].g);
            ch=getchar();
        }//由於輸入時兩個字符串之間會間隔一個空格,所以咱們getchar()掉這個空格,getchar的這個空格記爲ch,當ch='\n'(即說明讀到了回車),那麼很顯然的,就不該該讀下去了
  3. 以前sy講得:(感受咱們的是差很少的嘞qwq)
    char bj=' ',i=1;//bj即爲標記,i爲數組下標(多個數用數組比較方便)
      while(bj==' ')//由於輸完數要按空格
      {cin>>a[++i];
      bj=getchar();
     
    一行內輸入n個整數
  4. 神仙們的寫法:
    //樓下捕捉一隻yjk神仙
    while(cin>>s[++n]);
    //好像神仙們都是這麼寫的,就我這種蒟蒻寫的這麼複雜emm

而後由於方便計算,我把str和end加入了這n個單詞以後,在字典有的單詞的基礎上+2

//輸入部分
scanf("%s",str);
    scanf("%s",end);
    len=strlen(str);
    while(ch!='\n'){
        n++;
        scanf("%s",dic[n].g);
        ch=getchar();
    }
    for(int i=0;i<len;i++) dic[n+1].g[i]=str[i],dic[n+2].g[i]=end[i];
    n+=2;ss=n-1;ee=n;

next.由於數據比較小嘛,因此個人想法是開一個二維數組cy(chayi)[i][j],表示第i個單詞與第j個單詞的差別,而後大概應該多是用dfs計算,而後出結果;對於預處理:

  • 由於每一個單詞長度都不超過5,因此直接爆掃就能夠了;爲了看着比較簡潔好看,咱們寫一個bj(比較)函數;二重循環(爲了減小時間,咱們能夠把j從i+1開始循環,而後雙向存儲) 注意:cy[i][i]=0;(其實這個卻是也不重要由於dfs時會忽略i==j的狀況)
  • 對於bj函數,返回的是第i個單詞與第j個單詞相差的字母數量;
    //比較函數與預處理
    int bj(char a[],char b[]){
        int c=0;
        for(int i=0;i<len;i++)
          if(a[i]!=b[i]) c++;
        return c;
    }
    ……
    
    for(int i=1;i<=n;i++)
          for(int j=i+1;j<=n;j++)
             cy[j][i]=cy[i][j]=bj(dic[i].g,dic[j].g),cy[i][i]=0;

end.代碼的核心dfs部分:

  1. 定義兩個變量進行dfs:begin/*表示從哪一個單詞開始搜索下一個單詞*/,ans/*記錄進行了幾回變換*/
  2. 在主程序中dfs(ss/*表示起點的編號*/,1/*由樣例可知,str與end也要算在內,所以從1開始*/
  3. 先是臨界條件:噹噹前dfs到的編號恰好是end的標號ee時,用f數組記錄下這個解(顯然dfs會搜索出全部轉化狀況,而咱們只取最小的一種,所以要把每一種記錄下來,最後sort求解)return 1(對於這個return 1是用來判斷是否有解的)
  4. vis數組,用來判斷某一個點是否已經搜索過
  5. 定義一個next,利用for循環找到一個與begin的差別只有1的點[若是沒有顯然這種狀況不成立,也就是無解,所以定義一個bj=0,若是找到了差別是1的點,bj=1,在dfs的最後,若是bj=0,就說明無解,返回0],令next=i;標記vis[next]爲已經搜索(1);bj=1;而後搜索(next,ans+1);記得回溯使vis[next]=0;

以上就是大體算法流程。

CODE:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>

using namespace std;

char str[5],end[5],ch;
struct node1{
    char g[5];
}dic[31];
int n,cy[35][35],len,ss,ee,ans,f[100],cnt;

int bj(char a[],char b[]){
    int c=0;
    for(int i=0;i<len;i++)
      if(a[i]!=b[i]) c++;
    return c;
}
bool vis[31];

int solve(int begin,int ans){
    if(begin==ee) {
        f[++cnt]=ans;
        return 1;
    }
    int next;
    int bj=0;
    for(int i=1;i<=n;i++){
        if(vis[i]) continue;
        if(i==begin) continue;
        if(cy[begin][i]!=1) continue;
        
           next=i;vis[next]=1;
           bj=1;
           solve(next,ans+1);
           vis[next]=0;
    }
    if(!bj) return 0;
}

int main(){
//    freopen("word2.in","r",stdin);
//    freopen("word.out","w",stdout);
    scanf("%s",str);
    scanf("%s",end);
    len=strlen(str);
    while(ch!='\n'){
        n++;
        scanf("%s",dic[n].g);
        ch=getchar();
    }
    for(int i=0;i<len;i++) dic[n+1].g[i]=str[i],dic[n+2].g[i]=end[i];
    n+=2;ss=n-1;ee=n;
    for(int i=1;i<=n;i++)
      for(int j=i+1;j<=n;j++)
         cy[j][i]=cy[i][j]=bj(dic[i].g,dic[j].g),cy[i][i]=0;
    vis[ss]=1;
    if(solve(ss,1)==0)cout<<"0"<<endl;
    else{
        sort(f+1,f+cnt+1);
        cout<<f[1]<<endl;
    }
    return 0;
}

而後咱們看一下標程:

CODE:

//加一句註釋提醒本身並不想看標程,改天再看吧qwq
#include<cstdio> #include<iostream> #include<queue> #include<cstring> using namespace std; struct node{ string s; int dep; }; queue<node>q; string ss,st,s[31]; int vis[31]; int n=0; int can(string s,string t){ if(s.size()!=t.size()) return 0; int c=0; for(int i=0;i<s.size();i++) if(s[i]!=t[i]) c++; return c==1; } int bfs(){ memset(vis,0,sizeof(vis)); q.push((node){ss,1}); while(!q.empty()){ node cur=q.front();q.pop(); if(cur.s==st) return cur.dep;//是目標 if(can(cur.s,st)) return cur.dep+1;//再一步就是目標 for(int i=0;i<n;i++) if(!vis[i]&&can(cur.s,s[i])){ q.push((node){s[i],cur.dep+1}); vis[i]=1; } } return 0; } int main(){ freopen("word.in","r",stdin); freopen("word.out","w",stdout); cin>>ss>>st; while(cin>>s[n++]); cout<<bfs()<<endl; return 0; }

end-

相關文章
相關標籤/搜索