題目描述 所謂蟲食算,就是原先的算式中有一部分被蟲子啃掉了,需要我們根據剩下的數字來判定被啃掉的字母。來看一個簡單的例子: 43#9865#045 +8468#6633 44445509678 其中#號代表被蟲子啃掉的數字。根據算式,我們很容易判斷:第一行的兩個數字分別是5和3,第二行的數字是5。 ...
題目描述
所謂蟲食算,就是原先的算式中有一部分被蟲子啃掉了,需要我們根據剩下的數字來判定被啃掉的字母。來看一個簡單的例子:
43#9865#045
+8468#6633
44445509678
其中#號代表被蟲子啃掉的數字。根據算式,我們很容易判斷:第一行的兩個數字分別是5和3,第二行的數字是5。
現在,我們對問題做兩個限制:
首先,我們只考慮加法的蟲食算。這裡的加法是N進位加法,算式中三個數都有N位,允許有前導的0。
其次,蟲子把所有的數都啃光了,我們只知道哪些數字是相同的,我們將相同的數字用相同的字母表示,不同的數字用不同的字母表示。如果這個算式是N進位的,我們就取英文字母表午的前N個大寫字母來表示這個算式中的0到N-1這N個不同的數字:但是這N個字母並不一定順序地代表0到N-1)。輸入數據保證N個字母分別至少出現一次。
BADC
- CBDA
DCCC 上面的算式是一個4進位的算式。很顯然,我們只要讓ABCD分別代表0123,便可以讓這個式子成立了。你的任務是,對於給定的N進位加法算式,求出N個不同的字母分別代表的數字,使得該加法算式成立。輸入數據保證有且僅有一組解
輸入輸出格式
輸入格式:
包含四行。第一行有一個正整數N(N<=26),後面的3行每行有一個由大寫字母組成的字元串,分別代表兩個加數以及和。這3個字元串左右兩端都沒有空格,從高位到低位,並且恰好有N位。
輸出格式:
包含一行。在這一行中,應當包含唯一的那組解。解是這樣表示的:輸出N個數字,分別表示A,B,C……所代表的數字,相鄰的兩個數字用一個空格隔開,不能有多餘的空格。
輸入輸出樣例
輸入樣例#1:5 ABCED BDACE EBBAA輸出樣例#1:
1 0 3 4 2
說明
對於30%的數據,保證有N<=10;
對於50%的數據,保證有N<=15;
對於全部的數據,保證有N<=26。
noip2004提高組第4題
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n;//讀入幾進位0.1.2.3...n-1 4 int res[26];//保存A.B..Z代表的數字 5 int used[26];//保存這個對應數字是否被用,因為題目說每個字母只能代表一個數 6 string a,b,c;//保存加數1,加數2,和 7 int flag = 0;//是否已找到符合條件的唯一解//加上這個多對了2個點// 8 //-----最多只能7個點了,原先是從abcd..填字母,改變 9 char pos[26];//保存從右往左,從上往下的字母出現順序,判斷的時候也按這個順序判斷 10 int usedZiMu[26];//保存該字母是否已經出現 11 12 //剪枝優化函數,來判斷當前的字母的數字取法是否可行 13 //題目就是一個可行與否的問題 14 int Check() 15 { 16 int i; 17 //看是否滿足 a+b==c 18 for (i=n-1;i>=0;i--) 19 { 20 char a1=a[i]-'A',b1=b[i]-'A',c1=c[i]-'A';//取三個數第i位置值 21 if(res[a1]!=-1 && res[b1]!=-1 && res[c1]!=-1)//3個數都知道-----3個點 22 { 23 if( (res[a1]+res[b1])%n!=res[c1] &&//無進位 24 (res[a1]+res[b1]+1)%n!=res[c1])//有進位 25 return 0; 26 } 27 //加上後面這些多對了1個點 28 if(res[a1]!=-1 && res[b1]!=-1 && res[c1]==-1)//如果只知道其中2個 29 { 30 int sum1,sum2;//sum1無進位,sum2有進位 31 sum1 = (res[a1]+res[b1])%n; 32 sum2 = (res[a1]+res[b1]+1)%n; 33 if (used[sum1] && used[sum2])//可能填在c1的數都用了肯定不行 34 return 0; 35 } 36 if (res[a1]!=-1 && res[b1]==-1 && res[c1]!=-1)//和與一個加數知道 37 { 38 int js1,js2;//js1無進位,js2有進位 39 js1 = (res[c1]-res[a1]+n)%n; 40 js2 = (res[c1]-res[a1]-1+n)%n; 41 if (used[js1] && used[js2])//可能填寫咋b1位置的數都被用了 42 return 0; 43 } 44 if (res[a1]==-1 && res[b1]!=-1 && res[c1]!=-1)//和與一個加數知道 45 { 46 int js1,js2;//js1無進位,js2有進位 47 js1 = (res[c1]-res[b1]+n)%n; 48 js2 = (res[c1]-res[b1]-1+n)%n; 49 if (used[js1] && used[js2])//可能填寫咋b1位置的數都被用了 50 return 0; 51 } 52 53 } 54 return 1; 55 } 56 /*剪枝策略只這樣寫,數據只過3個點 57 int Check() 58 { 59 int i; 60 //看是否滿足 a+b==c 61 for (i=0;i<=n-1;i++) 62 { 63 char a1=a[i]-'A',b1=b[i]-'A',c1=c[i]-'A';//取三個數第i位置值 64 if(res[a1]!=-1 && res[b1]!=-1 && res[c1]!=-1) 65 { 66 if( (res[a1]+res[b1])%n!=res[c1] &&//無進位 67 (res[a1]+res[b1]+1)%n!=res[c1])//有進位 68 return 0; 69 } 70 71 } 72 return 1; 73 } 74 */ 75 //嚴格判斷當前所有字母的填數滿足等式否 76 int OK() 77 { 78 int i; 79 int jinwei=0; 80 int jiahe; 81 for (i=n-1; i>=0; i--) 82 { 83 char a1=a[i]-'A',b1=b[i]-'A',c1=c[i]-'A'; 84 85 jiahe = (res[a1]+res[b1]+jinwei)%n;//計算和 86 jinwei =( res[a1]+res[b1]+jinwei)/n;//計算進位 87 if (jiahe!=res[c1]) return 0; 88 } 89 if (jinwei>0) return 0; 90 return 1; 91 } 92 void dfs(int k)//深搜,利用系統的堆棧枚舉 93 { 94 int i; 95 if (flag) return ;//已找到解 96 if (!Check()) return;//現在的方法不合理--從if (!used[i]&&Check())移到這裡多了1個點共7個了 97 if(k==n)//找到可行解且唯一(題目得知),輸出 98 { 99 if (OK())//如果當前所有字母填數滿足等式則輸出 100 { 101 for(i=0; i<=n-2; i++) cout<<res[i]<<' '; 102 cout<<res[n-1]<<endl; 103 flag=1; 104 } 105 return ; 106 } 107 //在第k層,也就是第k個字母所可能取得數為0...n-1中未用值枚舉 108 for (i=n-1; i>=0; i--) 109 { 110 //如果i還沒被占用,且滿足剪枝條件,則進行下層遍歷 111 if (!used[i] ) 112 { 113 used[i]=1;//i被占用 114 res[pos[k]]=i;//第k個字母取數字i 115 dfs(k+1); 116 used[i]=0;//i被釋放,可以被其他字母占用 117 res[pos[k]]=-1;//第k個字母釋放 118 } 119 } 120 return ; 121 } 122 123 int main() 124 { 125 int k=0,i; 126 //讀入數據 127 cin>>n; 128 cin>>a>>b>>c; 129 memset(res,-1,sizeof(res)); 130 memset(pos,-1,sizeof(pos)); 131 //初始化 132 for (i=n-1; i>=0; i--)//從右向左 133 { 134 char a1=a[i]-'A',b1=b[i]-'A',c1=c[i]-'A';//全部轉成對應數字下標 135 if (!usedZiMu[a1]) ///從上往下 136 { 137 usedZiMu[a1]=1; 138 pos[k++] = a1; 139 } 140 if (!usedZiMu[b1]) 141 { 142 usedZiMu[b1]=1; 143 pos[k++] = b1; 144 } 145 if (!usedZiMu[c1]) 146 { 147 usedZiMu[c1]=1; 148 pos[k++] = c1; 149 } 150 } 151 dfs(0); 152 return 0; 153 }