題目描述 Description
所謂蟲食算,就是原先的算式中有一部分被蟲子啃掉了,需要我們根據剩下的數字來判定被啃掉的字母。來看一個簡單的例子:
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個不同的字母分別代表的數字,使得該加法算式成立。輸入數據保證有且僅有一組解,
輸入描述 Input Description
輸入文件alpha.in包含4行。第一行有一個正整數N(N<=26),後面的3行每行有一個由大寫字母組成的字符串,分別代表兩個加數以及和。這3個字符串左右兩端都沒有空格,從高位到低位,並且恰好有N位。
輸出描述 Output Description
輸出文件alpha.out包含一行。在這一行中,應當包含唯一的那組解。解是這樣表示的:輸出N個數字,分別表示A,B,C……所代表的數字,相鄰的兩個數字用一個空格隔開,不能有多餘的空格。
樣例輸入 Sample Input
5
ABCED
BDACE
EBBAA
樣例輸出 Sample Output
1 0 3 4 2
數據範圍及提示 Data Size & Hint
對於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;
}