【暴力搜索】[NOIP 2004]虫食算
题目http://blog.csdn.net/JeremyGJY/article/details/50611568
首先把每一个式子上的字母按照从右到左,从上到下的顺序存储下来,依次枚举每一个字母分别代表哪一个数字,然后每一次check一下当前的方案是否可行,只用考虑当前一列三个数字都知道了的情况,然后就是这样还有一个优化关键就是枚举数字的时候倒着枚举,具体原因我也不知道,反正就是要快一些。。。
#include <cstdio>
#include <cstring>
#include <vector>
#include <iostream>
#include <algorithm>
#include <cstdlib>
using namespace std;
const int MAXN = 26;
char s1[MAXN+5], s2[MAXN+5], s3[MAXN+5];
int i1[MAXN+3], i2[MAXN+5], i3[MAXN+5];
int val[MAXN+5], n, use[MAXN+5], step[MAXN*3+5];
bool check(){
int jw = 0, t1, t2, t3;
for(int i=n; i>=1; i--){
t1 = val[s1[i]-'A'], t2 = val[s2[i]-'A'], t3 = val[s3[i]-'A'];
if(t1 != -1 && t2 != -1 && t3 != -1){
if(jw == -1){
if((t1 + t2 + 1) % n == t3){
jw = (t1 + t2 + 1)/n;
continue;
}else if((t1 + t2) % n == t3){
jw = (t1 + t2)/n;
continue;
}
return false;
}else{
if((t1 + t2 + jw) % n != t3)
return false;
else jw = (t1 + t2 + jw) / n;
}
}else jw = -1;
}
return true;
}
void dfs(int u){
if(u > n*3){
printf("%d" , val[0]);
for(int i=1;i<n;i++)
printf(" %d", val[i]);
puts("");
exit(0);
}
if(val[step[u]] != -1){
dfs(u+1);
return ;
}
for(int i=n-1;i>=0;i--){
if(use[i]!=-1 && use[i]!=step[u]) continue;
use[i] = step[u], val[step[u]] = i;
if(!check()){
use[i] = -1;
val[step[u]] = -1;
continue;
}
dfs(u+1);
use[i] = val[step[u]] = -1;
}
}
int main(){
memset(use, -1, sizeof use);
memset(val, -1, sizeof val);
scanf("%d" ,&n);
scanf("%s%s%s", s1+1, s2+1, s3+1);
for(int i=n;i>=1;i--)
step[(n-i)*3+1] = s1[i]-'A', step[(n-i)*3+2] = s2[i]-'A', step[(n-i)*3+3] = s3[i]-'A';
dfs(1);
return 0;
}
/*
1/按照先后顺序处理出字母出现顺序
2/枚举每一个字母代表的数字
3/检查是否可行如果可行重复2直到所有数字枚举完成
*/
另有高斯消元算法请见高斯消元大法好