[WIKIOI 1064]蟲食算(高斯消元+深度優先搜索)

 所謂蟲食算,就是原先的算式中有一部分被蟲子啃掉了,需要我們根據剩下的數字來判定被啃掉的字母。來看一個簡單的例子:

       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個不同的字母分別代表的數字,使得該加法算式成立。輸入數據保證有且僅有一組解,

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

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

5
ABCED
BDACE
EBBAA

1 0 3 4 2

對於30%的數據,保證有N<=10;
對於50%的數據,保證有N<=15;
對於全部的數據,保證有N<=26。


這道題還是要倒過來搜索纔可以, 還有一些剪枝優化, 最後貼個高斯消元.


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char s[4][27];
int n,now;
int a[27],b[27],c[27];
bool goal;
bool Judge()
{
     int temp=0,k=0;
     for (int i=n-1;i>=0;--i)
     {
         temp=(b[s[1][i]-'A']+b[s[2][i]-'A']+k)%n;
         k=(b[s[1][i]-'A']+b[s[2][i]-'A']+k)/n;
         if (temp!=b[s[3][i]-'A']) return 0;
     }
     return 1;
}
     
bool Cleck()
{
     int temp,t1,t2,t3;
     for (int i=n-1;i>=0;--i)
     {
         t1=s[1][i]-'A',t2=s[2][i]-'A',t3=s[3][i]-'A';
         if (b[t1]!=-1 && b[t2]!=-1 && b[t3]!=-1) 
            if ((b[t1]+b[t2]+1)%n==b[t3] || (b[t1]+b[t2])%n==b[t3]) continue; else return 0;
         if (b[t1]!=-1 && b[t2]!=-1)
         {
                       temp=(b[t1]+b[t2])%n;
                       if (a[temp]==-1 || a[(temp+1)%n]==-1) continue; else return 0;
         }
         if (b[t1]!=-1 && b[t3]!=-1)
         {
                       temp=b[t3]-b[t1];
                       if (temp>=0 && a[temp]==-1) continue;
                       temp+=n;
                       if (temp>=0 && a[temp]==-1) continue;
                       temp=b[t3]-b[t1]-1;
                       if (temp>=0 && a[temp]==-1) continue;
                       temp+=n;
                       if (temp>=0 && a[temp]==-1) continue;
                       return 0;
         }
         if (b[t2]!=-1 && b[t3]!=-1)
         {
                       temp=b[t3]-b[t2];
                       if (temp>=0 && a[temp]==-1) continue;
                       temp+=n;
                       if (temp>=0 && a[temp]==-1) continue;
                       temp=b[t3]-b[t2]-1;
                       if (temp>=0 && a[temp]==-1) continue;
                       temp+=n;
                       if (temp>=0 && a[temp]==-1) continue;
               return 0;
         }
     }
     return 1;
}

void DFS(int k)
{
     if (k>n)
     {
             if (Judge()) goal=1;
             return;
     }
     for (int i=n-1;i>=0;--i)
         if (a[i]==-1)
         {
                      a[i]=c[k];
                      b[c[k]]=i;
                      if (Cleck()) DFS(k+1);
                      if (goal) return;
                      a[i]=-1;
                      b[c[k]]=-1;
         }
}

int main()
{
    scanf("%d",&n);
    scanf("%s",s[1]);
    scanf("%s",s[2]);
    scanf("%s",s[3]);
    memset(a,255,sizeof(a));
    for (int i=n-1;i>=0;--i)
        for (int j=1;j<=3;++j)
            if (b[s[j][i]-'A']==0)
            {
                                b[s[j][i]-'A']=-1;
                                c[++now]=s[j][i]-'A';
            }
    DFS(1);
    printf("%d",b[0]);
    for (int i=1;i<n;++i) printf(" %d",b[i]);
    printf("\n");
    return 0;
}



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