【搜索】$P1092$虫食算
【搜索】\(P1092\)蟲食算
題目鏈接
首先,我們只考慮加法的蟲食算。這里的加法是N進制加法,算式中三個數都有N位,允許有前導的0。
其次,蟲子把所有的數都啃光了,我們只知道哪些數字是相同的,我們將相同的數字用相同的字母表示,不同的數字用不同的字母表示。如果這個算式是N進制的,我們就取英文字母表午的前N個大寫字母來表示這個算式中的0到N-1這N個不同的數字:但是這N個字母并不一定順序地代表0到N-1。輸入數據保證N個字母分別至少出現一次。輸入數據保證有且僅有一組解。
輸入格式
包含四行。
第一行有一個正整數\(N(N \leq 26)\)。
后面的三行,每行有一個由大寫字母組成的字符串,分別代表兩個加數以及和。這3個字符串左右兩端都沒有空格,從高位到低位,并且恰好有N位。
輸出格式
一行,即唯一的那組解。
解是這樣表示的:輸出N個數字,分別表示A,B,C,…所代表的數字,相鄰的兩個數字用一個空格隔開,不能有多余的空格。
對于30%的數據,保證有\(N \leq 10\);
對于50%的數據,保證有\(N \leq 15\);
對于全部的數據,保證有\(N \leq 26\)。
Solution
搜索是比較好想的。但若直接枚舉全排列需要n!,那么需要剪枝。
考慮加法,進位的話只會進1,所以如果(A + B) % n != C && (A + B +1) % n != C,顯然不合法。然后因為三個數都是N位,所以最高位不可能進位。
那么什么搜索順序會更優呢?從右往左,也就是從低位到高位。從右往左,按照字母出現順序搜索,能在很大程度上提高剪枝效率。
最后,最關鍵的一點,是一個exit(0)的應用。第一次知道這到底是個什么。
exit(0):正常運行程序并退出程序。 exit 是一個函數。 exit是系統調用級別的,它表示了一個進程的結束。 exit是進程的退出。 exit是操作系統提供的(或者函數庫中給出的)。 exit函數是退出應用程序,刪除進程使用的內存空間,并將應用程序的一個狀態返回給OS,這個狀態標識了應用程序的一些運行信息,這個信息和機器和操作系統有關,一般是 0 為正常退出,非0 為非正常退出。 6. 非主函數中調用return和exit效果很明顯,但是在main函數中調用return和exit的現象就很模糊,多數情況下現象都是一致的。
#include <algorithm> #include <iostream> #include <cstdio> using namespace std; long long read(){long long x = 0; int f = 0; char c = getchar();while(c < '0' || c > '9') f |= c == '-', c = getchar();while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();return f? -x:x; }int a[30], b[30], c[30], num[30], qu[30], n, cnt; char s1[30], s2[30], s3[30]; bool used[30]; bool ok(){//最后判斷一下是否滿足等式for(int i = n - 1, x = 0; i >= 0; --i){int A = num[a[i]], B = num[b[i]], C = num[c[i]];if((A + B + x) % n != C) return 0;x = (A + B + x) / n;}return 1; } void print(){//輸出printf("%d", num[0]);for(int i = 1; i < n; ++i) printf(" %d", num[i]);exit(0);//減少遞歸返回時間 } void dfs(int x){if(num[a[0]] + num[b[0]] >= n) return;//最高位沒有進位for(int i = n - 1; i >= 0; --i){int A = num[a[i]], B = num[b[i]], C = num[c[i]];if(A == -1 || B == -1 || C == -1) continue;if((A + B) % n != C && (A + B + 1) % n != C) return;//判每一位是否合法}if(x == n){if(ok()) print();return;}for(int i = n - 1; i >= 0; --i)if(!used[i]){num[qu[x]] = i, used[i] = 1;dfs(x + 1);num[qu[x]] = -1, used[i] = 0;//回溯} } void Sort(int x){//預處理遞歸枚舉順序if(!used[x]) used[x] = 1, qu[cnt++] = x; } int main(){freopen("1.txt", "r", stdin);freopen("1.out", "w", stdout);n = read();scanf("%s%s%s", s1, s2, s3);for(int i = 0; i < n; ++i)a[i] = s1[i] - 'A', b[i] = s2[i] - 'A', c[i] = s3[i] - 'A', num[i] = -1;for(int i = n - 1; i >= 0; --i){Sort(a[i]);//預處理順序Sort(b[i]);Sort(c[i]);}for(int i = 0; i < n; ++i) used[i] = 0;dfs(0);return 0; }轉載于:https://www.cnblogs.com/kylinbalck/p/11307087.html
總結
以上是生活随笔為你收集整理的【搜索】$P1092$虫食算的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 爬虫之基于线程池异步抓取
- 下一篇: PAT乙级1023