【暴力搜索】[NOIP 2004]虫食算

题目http://blog.csdn.net/JeremyGJY/article/details/50611568
首先把每一个式子上的字母按照从右到左,从上到下的顺序存储下来,依次枚举每一个字母分别代表哪一个数字,然后每一次check一下当前的方案是否可行,只用考虑当前一列三个数字都知道了的情况,然后就是这样还有一个优化关键就是枚举数字的时候倒着枚举,具体原因我也不知道,反正就是要快一些。。。

#include <cstdio>
#include <cstring>
#include <vector>
#include <iostream>
#include <algorithm>
#include <cstdlib>
using namespace std;
const int MAXN = 26;
char s1[MAXN+5], s2[MAXN+5], s3[MAXN+5];
int i1[MAXN+3], i2[MAXN+5], i3[MAXN+5];
int val[MAXN+5], n, use[MAXN+5], step[MAXN*3+5];
bool check(){
    int jw = 0, t1, t2, t3;
    for(int i=n; i>=1; i--){
        t1 = val[s1[i]-'A'], t2 = val[s2[i]-'A'], t3 = val[s3[i]-'A'];
        if(t1 != -1 && t2 != -1 && t3 != -1){
            if(jw == -1){
                if((t1 + t2 + 1) % n == t3){
                    jw = (t1 + t2 + 1)/n;
                    continue;
                }else if((t1 + t2) % n == t3){
                    jw = (t1 + t2)/n;
                    continue;
                }
                return false;
            }else{
                if((t1 + t2 + jw) % n != t3)
                    return false;
                else jw = (t1 + t2 + jw) / n;
            }
        }else jw = -1;
    }
    return true;
}
void dfs(int u){
    if(u > n*3){
        printf("%d" , val[0]);
        for(int i=1;i<n;i++)
            printf(" %d", val[i]);
        puts("");
        exit(0);
    }
    if(val[step[u]] != -1){
        dfs(u+1);
        return ;
    }
    for(int i=n-1;i>=0;i--){
        if(use[i]!=-1 && use[i]!=step[u]) continue;
        use[i] = step[u], val[step[u]] = i;
        if(!check()){
            use[i] = -1;
            val[step[u]] = -1;
            continue;
        }
        dfs(u+1);
        use[i] = val[step[u]] = -1;
    }
}
int main(){
    memset(use, -1, sizeof use);
    memset(val, -1, sizeof val);
    scanf("%d" ,&n);
    scanf("%s%s%s", s1+1, s2+1, s3+1);
    for(int i=n;i>=1;i--)
        step[(n-i)*3+1] = s1[i]-'A', step[(n-i)*3+2] = s2[i]-'A', step[(n-i)*3+3] = s3[i]-'A';
    dfs(1);

    return 0;
}
/*
1/按照先后顺序处理出字母出现顺序
2/枚举每一个字母代表的数字
3/检查是否可行如果可行重复2直到所有数字枚举完成
*/

另有高斯消元算法请见高斯消元大法好

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值