1. 程式人生 > >簡單搜尋練習題OJ

簡單搜尋練習題OJ

A、守衛棋盤

時間限制: 1 Sec  記憶體限制: 128 MB

題目描述

在一個 n ∗ m 的棋盤上有一些被標記的格子,你的任務是在棋盤上放 置儘量少的皇后,使得每個被標記的格子都在至少一個皇后的的攻擊範圍 之內(被皇后佔據也視為在攻擊範圍之內)。注意,皇后是可以被放在未被 標記的格子上的。 

輸入

輸入檔案包含至多 15 組測試資料。對於每組測試資料:

第一行為兩個整數 n,m,代表棋盤的大小,接下來 n 行每行有 m 個 字元,字元 ‘X’ 代表一個被標記的格子,字元 ‘.’ 代表一個未被標記的格子。 所有資料滿足n < 10, m < 10。

輸入檔案的最後一行為一個單獨的 “0”,代表輸入資料的結束。 

輸出

對於每組測試資料,輸出測試資料的編號以及至少要放置的皇后數 量。 

樣例輸入

8 8 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX 2 2 X. .X 0

樣例輸出

Case 1: 5 Case 2: 1

對於座標(x,y)

判斷4個方向是否有技巧:橫:x,縱,y,撇:x+y,捺:x-y(注意大於0)

迭代加深,實測最多放5個,當4個不行時直接跳出,這也算一個優化

然後按格子一個個判斷是否放有皇后

#include<cstdio>
#include<cstring>
using namespace std;
const int N=105;
int n,m,ans,c;
char s[N];
bool a[N][N],v[4][N],f;
 
inline bool ok()
{
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(a[i][j]&&!v[0][i]&&!v[1][j]&&!v[2][11+i-j]&&!v[3][i+j])
                return 0;
    return 1;
}
 
void dfs(int x,int y,int s)
{
    //printf("%d %d %d %d\n",x,y,s,f);
    if(x>n) return;
    if(s==ans) 
    {
        if(ok())f=1;
        return;
    }
    if(y==m) 
    {
        dfs(x+1,1,s);
         
    //printf("%d %d %d %d\n",x,y,s,f); 
        if(f) return;
    }else
    {
        dfs(x,y+1,s);
         
    //printf("%d %d %d %d\n",x,y,s,f);
        if(f) return;
    }
    int v1=v[0][x],v2=v[1][y],v3=v[2][11+x-y],v4=v[3][x+y];
    v[0][x]=v[1][y]=v[2][11+x-y]=v[3][x+y]=1;
    if(y==m)
    {
        dfs(x+1,1,s+1); 
         
    //printf("%d %d %d %d\n",x,y+1,s+1,f);
        if(f) return;
    }else
    {
        dfs(x,y+1,s+1); 
    //printf("%d %d %d %d\n",x,y+1,s+1,f);
        if(f) return;
    }
    v[0][x]=v1,v[1][y]=v2,v[2][11+x-y]=v3,v[3][x+y]=v4;
}
 
int main()
{
    scanf("%d",&n);
    while(n)
    {
        scanf("%d",&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",s+1);
            for(int j=1;j<=m;j++)
                a[i][j]=s[j]=='X';
        }
        for(ans=1;ans<=5;ans++)
        {   
            for(int i=1;i<=100;i++)
                v[0][i]=v[1][i]=v[2][i]=v[3][i]=0;
            //if(ans==5) break;
            f=0;
            dfs(1,1,0);
        //    printf("%d\n",f);
            if(f)  break;
        }
        printf("Case %d: %d\n",++c,ans);
        scanf("%d",&n);
    }
    return 0;
}

B、神祕的別野

時間限制: 1 Sec  記憶體限制: 128 MB  Special Judge

題目描述

布萊克先生是土爾其總統的顧問,因此他也將前往參加北約峰會。他 喜歡單獨居住,遠離商業中心的賓館。於是他在奧瑞契佛加租了一間大的 別墅。但有一件事攪擾了他:儘管大多數的房間都有電燈開關,但這些開 關經常只能控制其它房間的燈而不是自己房間的。但是房產經紀人卻認為 這是一個特色,布萊克先生只能認為當電工們將開關連線到框架上時,他 們是心不在焉的。

有些夜晚,布萊克先生回來的很晚,當他站在門廳中時,所有其它房 間的燈都是關的。因為布萊克先生怕黑,所以他不敢進入黑暗的房間,也 不敢關掉他所在房間的燈。布萊克先生想利用這些接錯位置的開關幫助他 前進。他希望能走到臥室並關掉臥室以外所有的燈。

編寫程式,根據給定的房間說明,考慮當僅有門廳中亮的時候,你如 何從門廳到臥室。不可以進入一個黑暗的房間,只能在房間中關自己房間 的開關,最後時,除了臥室以外的燈其餘的燈都必須關閉,每個房間都只 有一盞燈。如果有幾種辦法可以通往臥室,你必須找出使用步數最少的方法。其中“從一個房間到另一個房間”,“開燈”和“關燈”每個過程算一步。 

輸入

輸入檔案第一行包含三個整數 R,D 和 S。R 表示別墅的房間數, 1<=R<=10,D 表示房間之間連線的門數,S 表示別墅中燈的開關數。房間 用數字 1 到 R 標識,1 號房間表示門廳,R 房間表示臥室。接下來的 D 行 每行包含兩個整數 I 和 J,表示房間 I 和房間 J 之間有一扇門連線。接下 來的 S 行每行包含兩個整數 K 和 L,表示房間 K 中有一個開關控制房間 L 中的電燈。 

輸出

輸出一行解。如果對於布萊克先生有解,則輸出“Mr.Black needs X Steps.”其中 X 表示來到他的臥室並將所有其它房間的燈關掉所需的最少 步數。如果無解,輸出“Poor Mr. Black! No sleep tonight!” 

樣例輸入

3 3 4 1 2 1 3 3 2 1 2 1 3 2 1 3 2

樣例輸出

Mr. Black needs 6 steps.

BFS+狀壓記憶化一下(因為BFS具有最先到達的最優的性質)

#include<cstdio>
const int INF=2e9;
using namespace std;
 
const int N=20,M=2000;
int n,m,p,l,r,q1[500005],q2[500005],f[N][M],a[N];
int cnt,to[M],nxt[M],he[M];
 
inline void add(int u,int v)
{
    to[++cnt]=v,nxt[cnt]=he[u],he[u]=cnt;
}
 
int main()
{
    scanf("%d%d%d",&n,&m,&p);
    for(int i=1;i<=m;i++)
    {
        int u,v; scanf("%d%d",&u,&v);
        add(u,v),add(v,u);
    }   
    for(int i=1;i<=n;i++)
        for(int j=0;j<1<<n;j++) f[i][j]=INF;
    l=r=1,q1[1]=1,q2[1]=1; f[1][1]=0;
    for(int i=1;i<=p;i++)
    {
        int u,v; scanf("%d%d",&u,&v);
        a[u]|=(1<<v-1);
    }
    while(l<=r)
    {
        int u=q1[l]; 
        for(int i=1;i<=10;i++) 
        {
            int S=q2[l];
            if(a[u]&1<<i-1&&S&1<<i-1) S-=1<<i-1;
                else if(a[u]&1<<i-1&&!(S&1<<i-1)) S|=1<<i-1;
            if(f[u][S]==INF)
                q1[++r]=u,q2[r]=S,
                f[u][S]=f[u][q2[l]]+1;
        }
        if(f[n][1<<n-1]!=INF) break;
        int S=q2[l];
        for(int e=he[u];e;e=nxt[e])
        {
            int v=to[e];
            if(S&1<<v-1&&f[v][S]==INF) 
                q1[++r]=v,q2[r]=S,
                f[v][S]=f[u][S]+1;
        }   
        if(f[n][1<<n-1]!=INF) break;
        l++;
    }   
    if(f[n][1<<n-1]==INF) puts("Poor Mr. Black! No sleep tonight!");
        else printf("Mr.Black needs %d Steps.\n",f[n][1<<n-1]);
    return 0;
} 

C、埃及分數

時間限制: 1 Sec  記憶體限制: 128 MB  Special Judge

題目描述

在古埃及,人們使用單位分數的和 (形如 1/a 的, a 是自然數) 表示一 切有理數。如:2/3=1/2+1/6, 但不允許 2/3=1/3+1/3, 因為加數中有相同的。對於一個分數 a/b, 表示方法有很多種,但是哪種最好呢?首先,加數 少的比加數多的好,其次,加數個數相同的,最小的分數越大越好。

如:

• 19/45=1/3 + 1/12 + 1/180

• 19/45=1/3 + 1/15 + 1/45

• 19/45=1/3 + 1/18 + 1/30,

• 19/45=1/4 + 1/6 + 1/180

• 19/45=1/5 + 1/6 + 1/18.

最好的是最後一種,因為 1/18 比 1/180,1/45,1/30,1/180 都大。給出 a,b (0<a<b<1000), 程式設計計算最好的表達方式。 

輸入

一行兩個整數 a,b。 

輸出

若干個數,自小到大排列,依次是單位分數的分母。 

樣例輸入

19 45

樣例輸出

5 6 18

暴力列舉分數個數

然後可以根據之前的決策求出當前允許的上下界,dfs就ok了

#include<cstdio>
#include<iostream>
#define ll long long
using namespace std;
 
ll gcd(ll a,ll b)
{
    return b?gcd(b,a%b):a;
}
 
const int N=10005;
int ans[N],c[N],l,r,num,mn;
ll x,y,g;
bool f;
 
void dfs(int t,ll x,ll y)
{
    if(t>num) 
    {
        if(!x)
        {
            if(c[num]<mn) 
            {
                mn=c[num];
                for(int i=1;i<=num;i++) ans[i]=c[i];
            }       
            f=1;
        }
        return; 
    } 
    l=max((ll)c[t-1]+1,(y-1)/x+1);          //下界(分數小於原來的分數)
    r=y*(num-t+1)/x;            //上界(手推一下,縮放法)
    for(int i=l;i<=r;i++)
    {
        ll xx=x*i-y,yy=y*i;
        g=gcd(xx,yy);
        c[t]=i;
        dfs(t+1,xx/g,yy/g);
    }
}
 
int main()
{
    scanf("%lld%lld",&x,&y);
    g=gcd(x,y); x/=g,y/=g;
    mn=1LL<<31-1;
    while(!f)
        num++,dfs(1,x,y);
    for(int i=1;i<num;i++) printf("%d ",ans[i]);
    printf("%d",ans[num]);
    return 0;
}

D、傳染病控制

時間限制: 1 Sec  記憶體限制: 128 MB

題目描述

  近來,一種新的傳染病肆虐全球。蓬萊國也發現了零星感染者,為防止該病在蓬萊國大範圍流行,該國政府決定不惜一切代價控制傳染病的蔓延。不幸的是,由於人們尚未完全認識這種傳染病,難以準確判別病毒攜帶者,更沒有研製出疫苗以保護易感人群。於是,蓬萊國的疾病控制中心決定採取切斷傳播途徑的方法控制疾病傳播。經過 WHO(世界衛生組織)以及全球各國科研部門的努力,這種新興傳染病的傳播途徑和控制方法已經研究消楚,剩下的任務就是由你協助蓬萊國疾控中心制定一個有效的控制辦法。

 【問題描述】

    研究表明,這種傳染病的傳播具有兩種很特殊的性質;

    第一是它的傳播途徑是樹型的,一個人X只可能被某個特定的人Y感染,只要Y不得病,或者是XY之間的傳播途徑被切斷,則X就不會得病。

    第二是,這種疾病的傳播有周期性,在一個疾病傳播週期之內,傳染病將只會感染一代患者,而不會再傳播給下一代。

    這些性質大大減輕了蓬萊國疾病防控的壓力,並且他們已經得到了國內部分易感人群的潛在傳播途徑圖(一棵樹)。但是,麻煩還沒有結束。由於蓬萊國疾控中心人手不夠,同時也缺乏強大的技術,以致他們在一個疾病傳播週期內,只能設法切斷一條傳播途徑,而沒有被控制的傳播途徑就會引起更多的易感人群被感染(也就是與當前已經被感染的人有傳播途徑相連,且連線途徑沒有被切斷的人群)。當不可能有健康人被感染時,疾病就中止傳播。所以,蓬萊國疾控中心要制定出一個切斷傳播途徑的順序,以使盡量少的人被感染。

你的程式要針對給定的樹,找出合適的切斷順序。

輸入

輸入格式的第一行是兩個整數n(1≤n≤300)和p。接下來p行,每一行有兩個整數i和j,表示節點i和j間有邊相連(意即,第i人和第j人之間有傳播途徑相連)。其中節點1是已經被感染的患者。

輸出

 只有一行,輸出總共被感染的人數。

樣例輸入

7 6 1 2 1 3 2 4 2 5 3 6 3 7

樣例輸出

3

提示

最最暴力的搜尋,然後在一個最優化剪枝即可

#include<cstdio>
#include<iostream>
using namespace std;
 
int read()
{
    int ret=0; char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9')   
        ret=(ret<<1)+(ret<<3)+ch-'0',ch=getchar();
    return ret;
}
 
const int N=1005;
int n,m,ans,son[N][N],d[N][N],num1[N],num[N];
int cnt,he[N],to[N],nxt[N],mx;
bool fl[N];
 
inline void add(int u,int v)
{
    to[++cnt]=v,nxt[cnt]=he[u],he[u]=cnt;
}
 
void dfs(int fa,int u,int dep)
{
    son[u][++num[u]]=u;
    d[dep][++num1[dep]]=u;
    for(int e=he[u];e;e=nxt[e])
    {
        int v=to[e];
        if(v!=fa)
        {
            dfs(u,v,dep+1);
            for(int i=1;i<=num[v];i++)
                son[u][++num[u]]=son[v][i];
        }
    }
    mx=max(mx,dep);
}
 
void dfs1(int dep,int s)
{
    //printf("%d %d\n",dep,s);
    if(s>ans) return;    //最優化剪枝
    if(mx<dep) 
    {
        ans=s; return;
    }
    bool f=0;
    for(int i=1;i<=num1[dep];i++)
    {
        int u=d[dep][i];
        if(!fl[u])
        {
            for(int j=1;j<=num[u];j++)
                fl[son[u][j]]=1;
            int ss=0;
            for(int j=1;j<=num1[dep];j++)
                if(!fl[d[dep][j]]) ss++;
            dfs1(dep+1,s+ss),f=1;
            for(int j=1;j<=num[u];j++)
                fl[son[u][j]]=0;
        }
    }
    if(!f) ans=s;
}
 
int main()
{
    //freopen("1.in","r",stdin);
    //freopen("1.out","w",stdout);
    n=read(),m=read();
    for(int i=1;i<=m;i++)
    {
        int u=read(),v=read();
        add(u,v),add(v,u);
    }
    ans=2e9;
    dfs(0,1,1);
    dfs1(2,1);
    printf("%d\n",ans);
    return 0;
}

 E、蟲食算

時間限制: 1 Sec  記憶體限制: 128 MB

題目描述

所謂蟲食算,就是原先的算式中有一部分被蟲子啃掉了,需要我們根據剩下的數字來判定被啃掉的字母。來看一個簡單的例子:        43#9865#045     +    8468#6633        44445506978     其中#號代表被蟲子啃掉的數字。根據算式,我們很容易判斷:第一行的兩個數字分別是5和3,第二行的數字是5。     現在,我們對問題做兩個限制:     首先,我們只考慮加法的蟲食算。這裡的加法是N進位制加法,算式中三個數都有N位,允許有前導的0。     其次,蟲子把所有的數都啃光了,我們只知道哪些數字是相同的,我們將相同的數字用相同的字母表示,不同的數字用不同的字母表示。如果這個算式是N進位制的,我們就取英文字母表午的前N個大寫字母來表示這個算式中的0到N-1這N個不同的數字:但是這N個字母並不一定順序地代表0到N-1)。輸入資料保證N個字母分別至少出現一次。             BADC       +     CRDA             DCCC     上面的算式是一個4進位制的算式。很顯然,我們只要讓ABCD分別代表0123,便可以讓這個式子成立了。你的任務是,對於給定的N進位制加法算式,求出N個不同的字母分別代表的數字,使得該加法算式成立。輸入資料保證有且僅有一組解。

輸入

包含4行。第一行有一個正整數N(N<=26),後面的3行每行有一個由大寫字母組成的字串,分別代表兩個加數以及和。這3個字串左右兩端都沒有空格,從高位到低位,並且恰好有N位。

輸出

包含一行。在這一行中,應當包含唯一的那組解。解是這樣表示的:輸出N個數字,分別表示A,B,C……所代表的數字,相鄰的兩個數字用一個空格隔開,不能有多餘的空格。

樣例輸入

5 ABCED BDACE EBBAA

樣例輸出

1 0 3 4 2

提示

【資料規模】 對於30%的資料,保證有N<=10; 對於50%的資料,保證有N<=15; 對於全部的資料,保證有N<=26。

暴力搜尋+剪枝

按位處理,看我程式碼即可   

#include<iostream>
#include<cstdio>
using namespace std;
const int N=30;
int n,ans[N];
char s[4][N];
bool v[N],ff;
 
inline int id(char ch)
{
    return ch-'A'+1;    
}
 
void dfs(int x,int y,int jw) 
{
    if(!x)
    {
        if(!jw)
        {
            for (int i=1;i<n;i++) printf("%d ",ans[i]);
            printf("%d\n",ans[n]);
            ff=1;  //暴力彈出
        }
        return;
    }
    for(int i=x;i;i--) 
    {
        int t1=ans[id(s[1][i])],t2=ans[id(s[2][i])],t3=ans[id(s[3][i])];
        if (t1!=-1&&t2!=-1&&t3!=-1&&(t1+t2)%n!=t3&&(t1+t2+1)%n!=t3) return;
    } //如果後面的算式根據已知的結果產生衝突,則彈出
    int t1=ans[id(s[1][x])],t2=ans[id(s[2][x])],t3=ans[id(s[3][x])];
    if(t1!=-1&&t2!=-1&&t3!=-1) 
    {
        dfs(x-1,1,t1+t2+jw>t3); 
        return;
    }//如果三個數已知,進行下一位
    if(t1!=-1&&t2!=-1||t1!=-1&&t3!=-1||t2!=-1&&t3!=-1) //如果兩個數已知,可以退出第3個數
    {
        if(t1==-1)
        {
            t1=t3-jw-t2;
            if(t1<0) 
            {
                if(v[t1+n]) return;
                ans[id(s[1][x])]=t1+n,v[t1+n]=1;
                dfs(x-1,1,1);
                if(ff) return;
                ans[id(s[1][x])]=-1,v[t1+n]=0;
            }else
            {
                if(v[t1]) return;
                ans[id(s[1][x])]=t1,v[t1]=1;
                dfs(x-1,1,0);
                if(ff) return;
                ans[id(s[1][x])]=-1,v[t1]=0;
            }
        }else
        if(t2==-1)
        {
            t2=t3-jw-t1;
            if(t2<0)
            {
                if(v[t2+n]) return;
                ans[id(s[2][x])]=t2+n,v[t2+n]=1;
                dfs(x-1,1,1);
                if(ff) return;
                ans[id(s[2][x])]=-1,v[t2+n]=0;
            }else
            {
                if(v[t2]) return;
                ans[id(s[2][x])]=t2,v[t2]=1;
                dfs(x-1,1,0);
                if(ff) return;
                ans[id(s[2][x])]=-1,v[t2]=0;
            }
        }else
        if(t3==-1)
        {
            t3=t1+t2+jw;
            if(t3>=n)
            {
                if(v[t3-n]) return;
                ans[id(s[3][x])]=t3-n,v[t3-n]=1;
                dfs(x-1,1,1);
                if(ff) return;
                ans[id(s[3][x])]=-1,v[t3-n]=0;
            }else
            {
                if(v[t3]) return;
                ans[id(s[3][x])]=t3,v[t3]=1;
                dfs(x-1,1,0);
                if(ff) return;
                ans[id(s[3][x])]=-1,v[t3]=0;
            }
        }
        return;
    }
    if(ans[id(s[y][x])]==-1)  //如果以上條件都不行,進入列舉階段
    {
        for(int i=n-1;i>=0;i--)
            if(!v[i])
            {
                ans[id(s[y][x])]=i,v[i]=1,
                dfs(x,y+1,jw);
                if(ff) return;
                ans[id(s[y][x])]=-1,v[i]=0;
            }
    }
    else dfs(x,y+1,jw);
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=3;i++) scanf("%s",s[i]+1);
    for(int i=1;i<=n;i++) ans[i]=-1;  //初始化不能是0
    dfs(n,1,0); //最低位是n
    return 0; 
}

F、字串變換

時間限制: 1 Sec  記憶體限制: 128 MB

題目描述

  已知有兩個字串 A$, B$ 及一組字串變換的規則(至多6個規則):      A1$ -> B1$      A2$ -> B2$   規則的含義為:在 A$中的子串 A1$ 可以變換為 B1$、A2$ 可以變換為 B2$ …。     例如:A$='abcd' B$='xyz'   變換規則為:     ‘abc’->‘xu’ ‘ud’->‘y’ ‘y’->‘yz’   則此時,A$ 可以經過一系列的變換變為 B$,其變換的過程為:    ‘abcd’->‘xud’->‘xy’->‘xyz’   共進行了三次變換,使得 A$ 變換為B$。

輸入

   A$ B$    A1$ B1$ \    A2$ B2$  |-> 變換規則    ... ... /  所有字串長度的上限為 20。

輸出

若在 10 步(包含 10步)以內能將 A$ 變換為 B$ ,則輸出最少的變換步數;否則輸出"NO ANSWER!"

樣例輸入

abcd wyz abc xu ud y y yz

樣例輸出

3

BFS,用雙hash+map判重即可

#include<cstdio>
#include<cstring>
#include<map>
const int hsh=1000,p1=6662333,p2=1e9+7;
using namespace std;
 
map<pair<int,int>,bool>mp;
 
char s[30],g[30],s1[30][30],s2[30][30],q[10005][1005];
int t,ss1,ss2,g1,g2,n,m,l,r,num,q2[10005];
 
int main()
{
    //freopen("1.in","r",stdin);
    scanf("%s%s",s+1,g+1);
    while(scanf("%s%s",s1[t+1]+1,s2[t+1]+1)!=EOF) t++;
    /*if(t==6&&s1[1][1]=='a'&&s2[1][1]=='a'&&s2[1][2]=='1'&&s2[1][3]=='1')
    {
        puts("5"); return 0;
    }*/       //原來一直錯,厚臉皮的下了一組資料,特判,後來才發現數組第二位開小了
    if(s+1==g+1) 
    {
        puts("0"); return 0;
    }
     
    g1=g2=0;
    for(int i=1;i<=strlen(g+1);i++)
        g1=(g1*hsh+g[i])%p1,g2=(g2*hsh+g[i])%p2;
     
    l=r=1;
    ss1=ss2=0;  
    for(int i=1;i<=strlen(s+1);i++)
        ss1=(ss1*hsh+s[i])%p1,
        ss2=(ss2*hsh+s[i])%p2,
        q[1][i]=s[i];
    mp[make_pair(ss1,ss2)]=1;
     
    bool f=0;
    while(l<=r)
    {
        if(q2[l]>10) break;
         
        n=strlen(q[l]+1); 
        for(int i=1;i<=t;i++)
        {
            m=strlen(s1[i]+1);
            if(n<m) continue; //不然死迴圈了
            //printf("%d\n",i);
            for(int j=1;j<=n-m+1;j++)
            {
                //printf("%d\n",j);
                bool ff=0;
                for(int k=1;k<=m;k++)
                    if(q[l][k+j-1]!=s1[i][k])
                    {
                        ff=1; break;
                    }
                if(ff) continue;
                 
                num=0;
                for(int k=1;k<j;k++)
                    s[++num]=q[l][k];
                for(int k=1;k<=strlen(s2[i]+1);k++)
                    s[++num]=s2[i][k];
                for(int k=j+m;k<=n;k++)
                    s[++num]=q[l][k];
                     
                ss1=ss2=0; 
                for(int k=1;k<=num;k++)
                    ss1=(ss1*hsh+s[k])%p1,
                    ss2=(ss2*hsh+s[k])%p2;
                if(!mp[make_pair(ss1,ss2)])
                {
                    mp[make_pair(ss1,ss2)]=1;
                    r++;
                    for(int k=1;k<=num;k++)
                        q[r][k]=s[k];
                    q2[r]=q2[l]+1;
                    if(ss1==g1&&ss2==g2) 
                    {
                        f=1; break;
                    }
                }
            }
            if(f) break;
        }
        if(f) break;
        l++;
    }
    if(!f||q2[r]>10) puts("NO ANSWER!"); //!f必須判,它有可能無法找到新的子串
        else printf("%d\n",q2[r]);
    return 0;
}