P1092虫食算题解

Posted sky-zxz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1092虫食算题解相关的知识,希望对你有一定的参考价值。

2018-10-24

题目链接

题目思路:

我就讲下剪枝操作吧。

三个式子从上到下为A,B,C

剪枝操作

1.从3个式子右边开始从上到下枚举字母对应数字。(搜索顺序关键)

2.末尾(A+B)%n!=C。

3.已知A,B,不知C,且C的可能数字已经使用。(这三个点从2000ms)

4.已知A.C,不知B,且B的可能数字已经使用。(一下剪枝成)

5.已知B,C,不知A,且A的可能数字已经使用。(100ms)

6.已知A,B,C,且A+B不等于C,且A+B+1不等于C。

7.已经A,B,C的最高位,且A+B有进位

8.逆序枚举数字。

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#define R register
using namespace std;
const int N=30;
int n,dis[N],flag[N],num,mp2[N];
char a[N],b[N],c[N],mp1[N];
inline int read(){ 
 R int s=0,w=1;R char ch=getchar();
 while(ch<0||ch>9){if(ch==-)w=-1;ch=getchar();} 
 while(ch>=0&&ch<=9) s=s*10+ch-0,ch=getchar();
 return s*w;
}
inline void write(R int x) {
    if(x < 0) {
        putchar(-);
        x = -x;
    }
    if(x >= 10) write(x / 10);
    putchar(x % 10 + 0);
}
inline int judge(){
        R int cnt=0;
        R int q=0,e=0,x=0;
        R int ss[N];
        for(R int i=n-1;i>=0;--i){
              ++cnt;
              ss[n-i-1]=x+dis[mp2[a[i]&31]]+dis[mp2[b[i]&31]];
              x=ss[n-i-1]/n;
              ss[n-i-1]%=n;
        }
        if(x)return 0;
        for(R int i=0;i<=n-1;++i)q=(q<<1)*5+ss[i];
        for(R int i=0;i<=n-1;++i)e=(e<<1)*5+dis[mp2[c[n-i-1]&31]];
        if(e==q)return 1;
        return 0;
}
inline int jianzhi(){
      if(dis[mp2[a[n-1]&31]]!=-1&&dis[mp2[b[n-1]&31]]!=-1&&dis[mp2[c[n-1]&31]]!=-1&&(dis[mp2[a[n-1]&31]]+dis[mp2[b[n-1]&31]])%n!=dis[mp2[c[n-1]&31]])return 1;
      if((dis[mp2[a[0]&31]]!=-1)&&(dis[mp2[b[0]&31]]!=-1)&&(dis[mp2[a[0]&31]]+dis[mp2[b[0]&31]]>=n))return 1;
        for(R int i=n-1;i>=0;--i){
                if((dis[mp2[a[i]&31]]!=-1)&&(dis[mp2[b[i]&31]]!=-1)&&(dis[mp2[c[i]&31]]==-1)&&(flag[(dis[mp2[a[i]&31]]+dis[mp2[b[i]&31]])%n]==1&&flag[(dis[mp2[a[i]&31]]+dis[mp2[b[i]&31]]+1)%n]==1))return 1;
           if((dis[mp2[a[i]&31]]!=-1)&&((dis[mp2[c[i]&31]]!=-1))&&(dis[mp2[b[i]&31]]==-1)&&flag[(dis[mp2[c[i]&31]]-dis[mp2[a[i]&31]]+n)%n]&&flag[(dis[mp2[c[i]&31]]-dis[mp2[a[i]&31]]-1+n)%n])return 1;
           if((dis[mp2[b[i]&31]]!=-1)&&((dis[mp2[c[i]&31]]!=-1))&&(dis[mp2[a[i]&31]]==-1)&&(flag[(dis[mp2[c[i]&31]]-dis[mp2[b[i]&31]]+n)%n])&&(flag[(dis[mp2[c[i]&31]]-dis[mp2[b[i]&31]]-1+n)%n]))return 1;
        if(dis[mp2[a[i]&31]]!=-1&&dis[mp2[b[i]&31]]!=-1&&dis[mp2[c[i]&31]]!=-1){
if((((dis[mp2[a[i]&31]]+dis[mp2[b[i]&31]])%n)!=dis[mp2[c[i]&31]])&&(((dis[mp2[a[i]&31]]+dis[mp2[b[i]&31]]+1)%n)!=dis[mp2[c[i]&31]]))return 1;         
        }
        }
        return 0;
}
void dfs(R int pos){
        if(jianzhi())return;
        if(pos==n+1){        
            if(judge()){
            for(R int i=A;i<=A+n-1;++i){
            write(dis[mp2[i&31]]);
            printf(" ");
            }
            exit(0);
            }
            return;
        }
        for(R int i=n-1;i>=0;--i){
            if(!flag[i]){
            dis[pos]=i;flag[i]=1;
            dfs(pos+1);
            dis[pos]=-1;flag[i]=0;
            }
        }
}
int main(){
      memset(dis,-1,sizeof(dis));
        n=read();scanf("%s",a);
        scanf("%s",b);scanf("%s",c);
        for(R int i=n-1;i>=0;--i){
              if(mp2[a[i]&31]==0){
                ++num;
                mp2[(a[i]&31)]=num;
                mp1[num]=a[i];
            }
                  if(mp2[c[i]&31]==0){
                  ++num;
                mp2[(c[i]&31)]=num;
                mp1[num]=c[i];
            }
                  if(mp2[b[i]&31]==0){
                ++num;
                mp2[(b[i]&31)]=num;
                mp1[num]=b[i];
            }
        }
        for(R int i=n-1;i>=0;--i){
        dis[1]=i;flag[i]=1;
        dfs(2);
        dis[1]=-1;flag[i]=0;
        }
        return 0;
}

 

以上是关于P1092虫食算题解的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P1092 虫食算

Luogu P1092 虫食算(枚举+剪枝)

洛谷P1092虫食算——深搜

P1092 虫食算

Luogu P1092 虫食算

P1092 虫食算