搜尋_DFS_CH2902_蟲食算
阿新 • • 發佈:2018-11-19
思路分析:
從相加的最低兩位開始考察, 注意利用已知兩個數可求第三個數進行剪枝. 注意在下面的AC程式碼中第59, 68和77行的i值如果從0開始遞增會TLE, 顯然這與測試用例有關係!!!
//CH2902_蟲食算 #include <iostream> #include <cstring> using namespace std; char s1[30], s2[30], s3[30]; int N; //val['A']為A對應數字, 未確定時val['A'] < 0, ok的第0位為1表示'A'對應數字已經確定 //used[i]為1表示值i對應字母已經確定, 為0表示未確定 int val[200], ok, used[30]; //將num填到空格val[ch], 並更新ok, used void fill(int ch, int num){ val[ch] = num, ok ^= 1 << num, used[num] = 1; } //如果當前方案成立, 返回true, 不成立返回false bool check(){ for(int i = N, ca = 0; i >= 1; --i){ int s = val[s1[i]] + val[s2[i]] + ca; if(s >= N) s %= N, ca = 1; else ca = 0; if(s != val[s3[i]]) return false; } return true; } //now當前正在考察的算式的列(最低位對應第0列), ca第now + 1列的進位值 void dfs(int now, int ca){ if(ok == (1 << N) - 1) return; int a = s1[now], b = s2[now], c = s3[now]; //如果a, b, c對應值均已確定 if(val[a] >= 0 && val[b] >= 0 && val[c] >= 0){ if(!(val[a] + val[b] + ca == val[c] || val[a] + val[b] + ca == N + val[c])) return; dfs(now - 1, (val[a] + val[b] + ca) / N); return; } //當前計算結果剪枝, 已知兩個加數的值 if(val[a] >= 0 && val[b] >= 0){ int sum = val[a] + val[b] + ca, tca = sum >= N? 1: 0; sum %= N; if(used[sum]) return; fill(c, sum), dfs(now - 1, tca); return; } //已知一個加數與和的值 if(val[a] >= 0 && val[c] >= 0){ if(val[c] >= val[a] + ca){ int tb = val[c] - val[a] - ca; if(used[tb]) return; fill(b, tb), dfs(now - 1, 0); return; } int tb = val[c] + N - val[a] - ca; if(used[tb]) return; fill(b, tb), dfs(now - 1, 1); return; } if(val[b] >= 0 && val[c] >= 0){ if(val[c] >= val[b] + ca){ int ta = val[c] - val[b] - ca; if(used[ta]) return; fill(a, ta), dfs(now - 1, 0); return; } int ta = val[c] + N - val[b] - ca; if(used[ta]) return; fill(a, ta), dfs(now - 1, 1); return; } //至此說明當前第now列至少有兩個值尚未確定 int arrv[50], tok, arru[30]; memcpy(arrv + 1, val + 'A', sizeof(int) * N), memcpy(arru, used, sizeof(int) * N), tok = ok; //a未確定 if(val[a] < 0){ for(int i = N; i >= 0; --i) if(!used[i]){ fill(a, i), dfs(now, ca); if(ok == (1 << N) - 1 && check()) return; else memcpy(val + 'A', arrv + 1, sizeof(int) * N), memcpy(used, arru, sizeof(int) * N), ok = tok; } return; } if(val[b] < 0){ for(int i = N; i >= 0; --i) if(!used[i]){ fill(b, i), dfs(now, ca); if(ok == (1 << N) - 1 && check()) return; else memcpy(val + 'A', arrv + 1, sizeof(int) * N), memcpy(used, arru, sizeof(int) * N), ok = tok; } return; } if(val[c] < 0) for(int i = N; i >= 0; --i) if(!used[i]){ fill(c, i), dfs(now, ca); if(ok == (1 << N) - 1 && check()) return; else memcpy(val + 'A', arrv + 1, sizeof(int) * N), memcpy(used, arru, sizeof(int) * N), ok = tok; } } int main(){ cin >> N >> s1 + 1 >> s2 + 1 >> s3 + 1; memset(val, 0xff, sizeof(val)); dfs(N, 0); for(int i = 'A'; i <= 'A' + N - 1; ++i) cout << val[i] << " "; }