NOIP2004【虫食算】(DFS)

这篇文章写得比较详细

https://blog.csdn.net/legan/article/details/52793129

对于搜索的优化:

1 从大往小搜

2 从原字符串的最低位开始搜,并且从上往下,这个可以记录在pos数组里

最后就是一些判断的函数了,文章写得挺详细的,看了他的才会写

#include<bits/stdc++.h>
using namespace std;
string a, b, c;
bool vis[30];
int pos[30], res[30], tot,n;
void parse()
{
    for (int i = n - 1; i >= 0; i--)//从右往左 顺序不能更改变,否则超时
    {
        int a1 = a[i] - 'A', b1 = b[i] - 'A', c1 = c[i] - 'A';//从上到下
        if (!vis[a1])
        {
            vis[a1] = true;
            pos[tot++] = a1;
        }
        if (!vis[b1])
        {
            vis[b1] = true;
            pos[tot++] = b1;
        }
        if (!vis[c1])
        {
            vis[c1] = true;
            pos[tot++] = c1;
        }
    }
}
bool valid()//最终检查
{
    int jinwei=0,sum=0;
    for (int i = n - 1; i >= 0; i--)
    {
        int a1 = a[i] - 'A', b1 = b[i] - 'A', c1 = c[i] - 'A';
        sum = (res[a1] + res[b1]+jinwei) % n;
        jinwei = (res[a1] + res[b1] + jinwei) / n;
        if (sum != res[c1]) return false;
    }
    if (jinwei != 0) return false;
    return true;
}
bool check()//粗略检查
{
    for (int i = n - 1; i >= 0; i--)//顺序可以改为0~n-1,时间会略有延长
    {
        // 对于一竖排上的3个数 a b c
        int a1 = a[i] - 'A', b1 = b[i] - 'A', c1 = c[i] - 'A';
        if (res[a1] != -1 && res[b1] != -1 && res[c1] != -1)
        {
            if ((res[a1] + res[b1]) % n != res[c1] && (res[a1] + res[b1] + 1) % n != res[c1]) return false;
        }
        else if (res[a1] != -1 && res[b1] != -1 && res[c1] == -1)
        {
            if (vis[(res[a1] + res[b1]) % n] && vis[(res[a1] + res[b1] + 1) % n]) return false;
        }
        else if (res[a1] != -1 && res[c1] != -1 && res[b1] == -1 ) //知道a c 
        {
            if (vis[(res[c1] - res[a1] + n) % n] && vis[(res[c1] - res[a1] - 1 + n) % n]) return false;
        }
        else if (res[a1] == -1 && res[b1] != -1 && res[c1] != -1)
        {
            if (vis[(res[c1] - res[b1] + n) % n] && vis[(res[c1] - res[b1] - 1 + n) % n]) return false;
        }
    }
    return true;
}
void dfs(int k)
{
    if (!check())  return;
    if (k == n)
    {
        if (valid())
        {
            for (int i = 0; i < n; i++)
                cout << res[i] << " \n"[i == n - 1];
            exit(0);//直接退出
        }
        return;
    }
    for (int i = n-1; i >=0 ; i--)//很重要,顺序不可以改变,否则超时
    {
        if (!vis[i]){
            vis[i] = true;
            res[pos[k]] = i;
            dfs(k + 1);
            res[pos[k]] = -1;
            vis[i] = false;
        }
    }
}
int main()
{
    cin >> n;
    cin>>a >> b >> c;
    parse();//处理pos数组,优化搜索
    memset(res, -1, sizeof(res));
    memset(vis, false, sizeof(vis));//这里一定要重新清0
    dfs(0);
    return 0;
}

 

posted @ 2019-03-06 20:32  TLE自动机  阅读(227)  评论(0编辑  收藏  举报