zoukankan      html  css  js  c++  java
  • 【NOIP 2004】 虫食算

    【题目链接】

               https://www.luogu.org/problemnew/show/P1092

    【算法】

                搜索 + 剪枝

                直接搜索显然会超时,考虑剪枝

                1 : 优化搜索顺序

                2 : 假设我们已经确定了一组(Ai,Bi,Ci),那么,如果(Ai + Bi) mod n 和(Ai + Bi + 1) mod n都不等于Ci,可以剪枝

    【代码】

              

    #include<bits/stdc++.h>
    using namespace std;
    
    int i,n,len;
    int a[30],ord[30];
    char A[30],B[30],C[30];
    bool used[30],vis[30];
    bool solved;
    
    inline bool ok()
    {
        int i;
        for (i = n; i >= 1; i--)
        {
              if (a[A[i]-'A'+1] == -1) continue;
              if (a[B[i]-'A'+1] == -1) continue;    
              if (a[C[i]-'A'+1] == -1) continue;
              if ((a[A[i]-'A'+1] + a[B[i]-'A'+1]) % n == a[C[i]-'A'+1]) continue;
              if ((a[A[i]-'A'+1] + a[B[i]-'A'+1] + 1) % n == a[C[i]-'A'+1]) continue;
              return false;
        }        
        return true;
    }
    inline void print()
    {
        int i;
        for (i = 1; i <= n; i++) printf("%d ",a[i]);
        printf("
    ");
    }
    inline bool check()
    {
        int t,b = 0;
        for (i = n; i >= 1; i--)
        {
                    t = (a[A[i]-'A'+1] + a[B[i]-'A'+1] + b) % n;
                    if (a[A[i]-'A'+1] + a[B[i]-'A'+1] + b >= n) b = 1;
                    else b = 0;
                    if (a[C[i]-'A'+1] == t) continue;
                    else return false;
        }
        if (b) return false;
        else return true;
    }
    inline void dfs(int dep)
    {
        int i;
        if (dep > n)
        {
            if (check())
            {
                solved = true;
                print();    
            }
            return;
        }    
        if (!ok()) return;
        for (i = n - 1; i >= 0; i--)
        {
            if (!used[i])
            {
                a[ord[dep]] = i;
                used[i] = true;
                dfs(dep+1);
                if (solved) return;
                used[i] = false;    
                a[ord[dep]] = -1;
            }        
        } 
    }
    
    int main() 
    {
            
        memset(a,255,sizeof(a));
        scanf("%d%s%s%s",&n,A+1,B+1,C+1);
        for (i = n; i >= 1; i--)
        {
            if (!vis[A[i]-'A'+1]) 
            {
                  ord[++len] = A[i] - 'A' + 1;
                  vis[A[i]-'A'+1] = true;
            }
            if (!vis[B[i]-'A'+1]) 
            {
                ord[++len] = B[i] - 'A' + 1;
                vis[B[i]-'A'+1] = true;
            }
            if (!vis[C[i]-'A'+1])
            {
                ord[++len] = C[i] - 'A' + 1;
                vis[C[i]-'A'+1] = true;
            }
        }
        dfs(1);
        
        return 0;
        
    }
  • 相关阅读:
    8086标志
    微内核
    枚举算法
    ajax
    面向对象技术概述
    ajax
    存储技术
    自然数组排列
    将搜索二叉树转换成双向链表
    在单链表中删除指定值的节点
  • 原文地址:https://www.cnblogs.com/evenbao/p/9278589.html
Copyright © 2011-2022 走看看