虫食算解题报告

一、顺序:逆序比顺序要快得多。
二、剪枝:
       每一步都判断当前为字母所配的值是否符合全部方程。
       这看起来好像是会很慢,每一次都要花O(n)的时间扫,但出奇的,却会收到非常好的效果。可以减掉大量废纸。
代码:
  #include<iostream> 
using namespace std;
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
typedef short hd;
hd n,ans[100],s[3][30];
char * ptr=new char [1000];
bool p[26];
inline void dfs(hd x,hd y,hd jx){
if(x<0&&!jx){
for(hd i=0;i<n;++i)printf("%hd ",ans[i]);
exit(0);
}
if(x<0)return;
for(hd i=x;i>-1;--i){
if(ans[s[0][i]]>-1&&ans[s[1][i]]>-1){
if(ans[s[2][i]]>-1&&!((ans[s[0][i]]+ans[s[1][i]])%n==ans[s[2][i]]||(ans[s[0][i]]+ans[s[1][i]]+1)%n==ans[s[2][i]]))
return;
if(ans[s[2][i]]<0&&p[(ans[s[0][i]]+ans[s[1][i]])%n]&&p[(ans[s[0][i]]+ans[s[1][i]]+1)%n])
return;
}
if(ans[s[2][i]]>-1){
if(ans[s[0][i]]>-1&&ans[s[1][i]]<0&&p[(n+ans[s[2][i]]-ans[s[0][i]])%n]&&p[(n+ans[s[2][i]]-1-ans[s[0][i]])%n])
return;
if(ans[s[0][i]]<0&&ans[s[1][i]]>-1&&p[(n+ans[s[2][i]]-ans[s[1][i]])%n]&&p[(n+ans[s[2][i]]-1-ans[s[1][i]])%n])
return;
}
}
if(y<2){
if(ans[s[y][x]]>-1)dfs(x,y+1,jx);
else{
hd other=!y,tmp1;
if(ans[s[2][x]]>-1&&ans[s[other][x]]>-1){
tmp1=ans[s[2][x]]-jx-ans[s[other][x]];
if(tmp1>-1&&!p[tmp1]){
p[tmp1]=1;
ans[s[y][x]]=tmp1;
dfs(x,y+1,jx);
p[tmp1]=0;
ans[s[y][x]]=-1;
}
tmp1=n+ans[s[2][x]]-jx-ans[s[other][x]];
if(tmp1<n&&!p[tmp1]){
p[tmp1]=1;
ans[s[y][x]]=tmp1;
dfs(x,y+1,jx);
p[tmp1]=0;
ans[s[y][x]]=-1;
}
return;
}
for(hd i=n-1;i>-1;--i)
if(!p[i]){
ans[s[y][x]]=i;
p[i]=1;
dfs(x,y+1,jx);
p[i]=0;
ans[s[y][x]]=-1;
}
}
}
else{
hd tmp=ans[s[0][x]]+ans[s[1][x]]+jx,tmpn=tmp%n;
tmp/=n;
if(ans[s[2][x]]>-1)
if(ans[s[2][x]]==tmpn)
dfs(x-1,0,tmp);
else return;
if(p[tmpn])return;
ans[s[2][x]]=tmpn;
p[tmpn]=1;
dfs(x-1,0,tmp);
p[tmpn]=0;
ans[s[2][x]]=-1;
}
}
inline void in(char * s){
hd tot=0;
while(*ptr<'A'||*ptr>'Z')++ptr;
while(*ptr>64||*ptr<91)s[tot++]=*ptr++;
}
int main(){
freopen("alpha.in","r",stdin);freopen("alpha.out","w",stdout);
memset(ans,-1,sizeof(ans));
fread(ptr,1,1000,stdin);
while(*ptr<'0'||*ptr>'9')++ptr;
while(*ptr>47&&*ptr<58)n=n*10+*ptr++-'0';
for(hd i=0;i<3;++i){
while(*ptr<'A'||*ptr>'Z')++ptr;
for(hd j=0;j<n;++j)
s[i][j]=*ptr++-'A';
}
dfs(n-1,0,0);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值