台州市椒江建设工程机械厂网站,随州做网站,wordpress vieu主题4.0,佛山网站优化公司P1092虫食算 这道题的思想并不复杂#xff0c;可是难点在于各种玄学剪枝。在仔细研究了题解大佬的剪枝原理后终于氵了过去。 先上代码#xff1a;
#includecstdio
#includecstring
#includealgorithm
using namespace std;const int MAXN100;
int n…P1092虫食算 这道题的思想并不复杂可是难点在于各种玄学剪枝。在仔细研究了题解大佬的剪枝原理后终于氵了过去。 先上代码
#includecstdio
#includecstring
#includealgorithm
using namespace std;const int MAXN100;
int n;
char s1[MAXN],s2[MAXN],s3[MAXN];
int key[MAXN],order[MAXN],used[MAXN];
int cnt0,A,B,C;void GetOrder(int x)
{if(used[x]0){used[x]1;order[cnt]x;}
}bool wrong()
{if(key[s1[0]]key[s2[0]]n) return true;for(int in-1;i--;i0){Akey[s1[i]]; Bkey[s2[i]]; Ckey[s3[i]];if(A-1 || B-1 || C-1) continue;if((AB)%n!C (AB1)%n!C){return true;}}return false;
}
bool ok()
{int x0;for(int in-1;i0;i--){Akey[s1[i]]; Bkey[s2[i]]; Ckey[s3[i]];if((ABx)%n!C)return false;x(ABx)/n;}return true;
}
void print()
{for(int i0;in-1;i){printf(%d ,key[iA]);}printf(%d,key[n-1A]);exit(0);
}
void dfs(int x)
{if(wrong()) return;if(xn){if(ok())print();return;}for(int in-1;i0;i--){if(used[i]0){used[i]1;key[order[x]]i;dfs(x1);used[i]0;key[order[x]]-1;}}
}int main()
{memset(s1,0,sizeof(s1));memset(s2,0,sizeof(s2));memset(s3,0,sizeof(s3));scanf(%d%s%s%s,n,s1,s2,s3);memset(used,0,sizeof(used));for(int in-1;i0;i--){GetOrder(s1[i]);GetOrder(s2[i]);GetOrder(s3[i]);}for(int iA;iZ;i){key[i]-1;}memset(used,0,sizeof(used));dfs(0);return 0;
}key数组保存的是译出的对照表s1,s2,s3保存的是题目给定的算式 重点是order数组和剪枝条件wrong() 先看剪枝条件吧 1.如果最高位加起来大于n显然需要剪枝 2.如果某一竖列已经确定且加(AB)%n!C (AB1)%n!C需要剪枝因为这是加法运算所以进位只能为1 但是在确定搜索顺序的时候我们发现如果从A0 B1这样没有规律的暴力搜索的话第二个剪枝条件只有到最后才能发挥作用因为可能只有大部分的数字被确定下来这一竖列才能确定那这样前面的就功亏一篑了所以为了解决这个问题我们加上order数组即按照order数组的顺序进行搜索 order数组的顺序就是一竖列一竖列的搜索这样只有前面的竖列都已经满足那个简单关系后才会进行后面的搜索所以会快很多。 因为最高位需要同时满足上面两个剪枝条件所以从高位向地位搜索效率更高 虽然能理解但是还是觉得自己做的话很难想到这么多的条件。在分析问题的时候要按照问题的特性去分析不要将自己局限在某一个小小的空间内。