【搜索】AcWing 184. 虫食算
作者:互联网
写完发现代码比别人的都长(悲
但是效率不错,在洛谷可以排在最优解第四页
分析
大致思路比较简单:
- 枚举位(使用 \(dfs\)),从低位开始枚举变量的值,如果没填过就选取 \([0, n-1]\) 中没选取过的值填上。
- 当前位三个变量都得到值后,检查是否合法。
- 当全部位都合法输出结果即可。
接下来考虑剪枝:
- 其实上面那个检查合法可以排除很多情况了。
- 对整个式子进行一遍扫描,逐位检查是否合法:如果当前位对应的值 \(a,b,c\) 同时不满足 \(a+b=c\) 以及 \(a+b+1=c\)(进位情况),那么一定不合法,停止继续向下搜索。
- 因为题目要求每个变量对应 \([0,n-1]\) 的一个值,所以整个算式看上去应当是数值的分布比较均匀的。因此,我们可以考虑给每一位的变量赋值的时候按照从大到小的顺序,因为如果按照从小到大枚举很容易将小的数都丢到低位去使得到达失败的概率很大。
实现
// Problem: 虫食算
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/186/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#pragma GCC optimize("O3")
#include<bits/stdc++.h>
using namespace std;
#define debug(x) cerr << #x << ": " << (x) << endl
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define x first
#define y second
using pii = pair<int, int>;
using ll = long long;
inline void read(int &x){
int s=0; x=1;
char ch=getchar();
while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
x*=s;
}
const int N=30;
int n;
string a, b, c;
int res[N];
int det;
int lowbit(int x){
return x&-x;
}
void get(vector<int> &d){
int t=det;
while(t) d.pb(__lg(lowbit(t))), t-=lowbit(t);
}
bool ng(){
rep(u,0,n-1){
int x=res[a[u]-'A'];
int y=res[b[u]-'A'];
int z=res[c[u]-'A'];
if(~x && ~y && ~z){
if((x+y)%n!=z && (x+y+1)%n!=z){
return true;
}
}
}
return false;
}
bool dfs(int u, int carry){
if(u==n){
return (!carry);
}
if(ng()) return false;
vector<int> fir, sec;
int pre1=res[a[u]-'A'], pre2=res[b[u]-'A'];
if(~pre1) fir.pb(res[a[u]-'A']);
else get(fir);
if(~pre2) sec.pb(res[b[u]-'A']);
else get(sec);
if(a[u]==b[u]){
reverse(all(fir));
for(auto i: fir){
res[a[u]-'A']=i;
det^=(1<<i);
int t=i+i+carry;
int pre3=res[c[u]-'A'];
if(~pre3){
if(t%n!=pre3){
det^=(1<<i);
continue;
}
}
else{
int val=t%n;
if(!(det&(1<<val))){
det^=(1<<i);
continue;
}
res[c[u]-'A']=val;
}
if(dfs(u+1, t/n)) return true;
det^=(1<<i);
res[c[u]-'A']=pre3;
}
}
else{
reverse(all(fir));
reverse(all(sec));
for(auto i: fir) for(auto j: sec) if(i!=j){
res[a[u]-'A']=i;
res[b[u]-'A']=j;
det^=(1<<i);
det^=(1<<j);
int t=i+j+carry;
int pre3=res[c[u]-'A'];
if(~pre3){
if(t%n!=pre3){
det^=(1<<i);
det^=(1<<j);
continue;
}
}
else{
int val=t%n;
if(!(det&(1<<val))){
det^=(1<<i);
det^=(1<<j);
continue;
}
res[c[u]-'A']=val;
}
if(dfs(u+1, t/n)) return true;
det^=(1<<i);
det^=(1<<j);
res[c[u]-'A']=pre3;
}
}
res[a[u]-'A']=pre1;
res[b[u]-'A']=pre2;
return false;
}
int main(){
cin>>n>>a>>b>>c;
reverse(all(a));
reverse(all(b));
reverse(all(c));
det=(1<<n)-1;
memset(res, -1, sizeof res);
dfs(0, 0);
rep(i,0,n-1) cout<<res[i]<<' ';
return 0;
}
标签:fir,ch,return,食算,res,int,184,define,AcWing 来源: https://www.cnblogs.com/Tenshi/p/16419303.html