【搜索】[NOIP2004]虫食算

题目
从各位开始按照字母出现的顺序枚举每个字母代表的值;
注意:要倒序枚举,这样比较快,虽然我也不知道为什么。
剪枝:1.搜索时每个数值只能由一个字母代表
2.搜索中如果发现有矛盾就回溯

#include<cstdio>
#define MAXN 26
#include<cstdlib>
#include<cstring>
int a[MAXN+10],n,e[MAXN+10];
char x[MAXN+10],y[MAXN+10],z[MAXN+10];
bool vis[MAXN+10];
void print(){
    for(int i=0;i<n-1;i++)
            printf("%d ",a[i]);
        printf("%d",a[n-1]);
}
void prepare(){
    int i,cnt=0;
    for(i=n-1;i>=0;i--){
        if(!vis[x[i]]){
            e[++cnt]=x[i];
            vis[x[i]]=1;
        }
        if(!vis[y[i]]){
            e[++cnt]=y[i];
            vis[y[i]]=1;
        }
        if(!vis[z[i]]){
            e[++cnt]=z[i];
            vis[z[i]]=1;
        }
    }
}
bool check(){
    int i,jw=0;
    for(i=n-1;i>=0;i--){
        if(a[x[i]]==-1||a[y[i]]==-1||a[z[i]]==-1)
            jw=-1;
        else{
            if(jw==-1){
                if((a[x[i]]+a[y[i]])%n==a[z[i]])
                    jw=(a[x[i]]+a[y[i]])/n;
                else if((a[x[i]]+a[y[i]]+1)%n==a[z[i]])
                    jw=(a[x[i]]+a[y[i]]+1)/n;
                else
                    return 0;
            }
            else if((a[x[i]]+a[y[i]]+jw)%n==a[z[i]])
                jw=(a[x[i]]+a[y[i]]+jw)/n;
                else
                    return 0;
        }
    }
    if(jw!=1)
        return 1;
    return 0;
}
void dfs(int i){
    if(i>n){
        print();
        exit(0);
    }
    int j;
    for(j=n-1;j>=0;j--){
        a[e[i]]=j;
        if(!vis[j]&&check()){
            vis[j]=1;
            dfs(i+1);
            vis[j]=0;
        }
    }
    a[e[i]]=-1;
}
int main()
{
    memset(a,-1,sizeof a);
    scanf("%d",&n);
    scanf("%s%s%s",x,y,z);
    for(int i=0;i<n;i++)
        x[i]-='A',y[i]-='A',z[i]-='A';
    prepare();
    memset(vis,0,sizeof vis);
    dfs(1);
}

另有高斯消元算法,请见【高斯消元】[NOIP2004]虫食算(这是正解)

posted @ 2015-08-26 20:10  outer_form  阅读(370)  评论(0编辑  收藏  举报