[NOIP2004 虫食算]

[关键字]:搜索

[题目大意]:不说了,自己找吧……

//===================================================================

[分析]:首先按照字母出现的顺序进行搜索,搜索每个字母分别代表什么数字。在每次搜索时都要剪枝,就是把当前的已知字母带到竖式中算一遍,如果出现矛盾情况就剪枝。矛盾情况就是:

1、同一列三个数都已知但(a+b)%n!=c

2、已知两个数但计算出的第三个数已经被其他字母占用。注意这里要处理进位的情况。

[代码]:

View Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

char s[4][27];
int n,now;
int a[27],b[27],c[27];
bool goal;

bool Judge()
{
//for (int i=0;i<n;++i) printf("%d ",b[i]);
//printf("\n");
int temp=0,k=0;
for (int i=n-1;i>=0;--i)
{
temp=(b[s[1][i]-'A']+b[s[2][i]-'A']+k)%n;
k=(b[s[1][i]-'A']+b[s[2][i]-'A']+k)/n;
if (temp!=b[s[3][i]-'A']) return 0;
}
return 1;
}

bool Cleck()
{
int temp,t1,t2,t3;
for (int i=n-1;i>=0;--i)
{
t1=s[1][i]-'A',t2=s[2][i]-'A',t3=s[3][i]-'A';
if (b[t1]!=-1 && b[t2]!=-1 && b[t3]!=-1)
if ((b[t1]+b[t2]+1)%n==b[t3] || (b[t1]+b[t2])%n==b[t3]) continue; else return 0;
if (b[t1]!=-1 && b[t2]!=-1)
{
temp=(b[t1]+b[t2])%n;
if (a[temp]==-1 || a[(temp+1)%n]==-1) continue; else return 0;
}
if (b[t1]!=-1 && b[t3]!=-1)
{
temp=b[t3]-b[t1];
if (temp>=0 && a[temp]==-1) continue;
temp+=n;
if (temp>=0 && a[temp]==-1) continue;
temp=b[t3]-b[t1]-1;
if (temp>=0 && a[temp]==-1) continue;
temp+=n;
if (temp>=0 && a[temp]==-1) continue;
return 0;
}
if (b[t2]!=-1 && b[t3]!=-1)
{
temp=b[t3]-b[t2];
if (temp>=0 && a[temp]==-1) continue;
temp+=n;
if (temp>=0 && a[temp]==-1) continue;
temp=b[t3]-b[t2]-1;
if (temp>=0 && a[temp]==-1) continue;
temp+=n;
if (temp>=0 && a[temp]==-1) continue;
return 0;
}
}
return 1;
}

void DFS(int k)
{
if (k>n)
{
if (Judge()) goal=1;
return;
}
for (int i=n-1;i>=0;--i)
if (a[i]==-1)
{
a[i]=c[k];
b[c[k]]=i;
//printf("%d %d %d\n",k,c[k],b[c[k]]);
if (Cleck()) DFS(k+1);
if (goal) return;
a[i]=-1;
b[c[k]]=-1;
}
}

int main()
{
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
scanf("%d",&n);
scanf("%s",s[1]);
scanf("%s",s[2]);
scanf("%s",s[3]);
memset(a,255,sizeof(a));
for (int i=n-1;i>=0;--i)
for (int j=1;j<=3;++j)
if (b[s[j][i]-'A']==0)
{
b[s[j][i]-'A']=-1;
c[++now]=s[j][i]-'A';
//printf("%d %c %d\n",now,s[j][i],c[now]);
}
//for (int i=1;i<=n;++i) printf("%d\n",c[i]);
DFS(1);
for (int i=0;i<n;++i) printf("%d ",b[i]);
return 0;
}



转载于:https://www.cnblogs.com/procedure2012/archive/2012/03/18/2405056.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值