zoukankan      html  css  js  c++  java
  • P1092 虫食算[搜索]

    这个式子是是由(Asim A+N)组成的,那么(Asim A+N)就只能等于(0sim N-1),因此我们每次对(Asim A+N)的取值做一个新的排列,然后judge一下当前状态是否可行,若可行直接输出解。

    显然(N!)过于庞大,需要剪枝。

    剪枝:

    假设一个这种情况:

    XXXAXXX
    XXXBXXX
    XXXCXXX
    

    其一,在一个排列中设(A+B=k)(A+B<C)时,在其它任意一个排列中,若(A+B<k),那么这个排列肯定不合法,(A+B<C+N)同理。

    其二,在一排里,进位至多为1,那么仅((A+B)\%N=C)((A+B+1)\%N=C)这两种情况成立。有了这个优化我们就不需要一了。

    其三,由于三排长度都是(N),意味着最高位没有进位。

    其四,在二的判断中,倘若我们能够早一些找到不合法的情况,那么这个题就可以得到更好的优化。显然,在检验二时,我们是从某一边的最边上那一排开始扫到末尾那一排,所有如果我们搜索时先搜出早一点扫到的那部分字母对应的数字,就会减少大量无用枝条。

    复杂度(O(EIS))

    参考代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<string>
    #include<cstdlib>
    #include<queue>
    #include<vector>
    #define INF 0x3f3f3f3f
    #define PI acos(-1.0)
    #define N 101
    #define MOD 2520
    #define E 1e-12
    using namespace std;
    inline int read()
    {
    	int f=1,x=0;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    	return x*f;
    }
    int n,num[N],q[N],cnt;
    char mp[4][N];
    bool v[N],use[N];
    inline void judge()
    {
    	int add=0;
    	for(int i=n;i>=1;--i){
    		if((num[mp[1][i]]+num[mp[2][i]]+add)%n==num[mp[3][i]])
    			add=(num[mp[1][i]]+num[mp[2][i]]+add)/n;
    		else return;
    	}
    	for(int i='A';i<'A'+n;++i)
    		printf("%d ",num[i]);
    	exit(0);
    }
    inline bool can()
    {
    	for(int i=n;i>=1;--i){
    		if(num[mp[1][i]]==-1||num[mp[2][i]]==-1||num[mp[3][i]]==-1) continue;
    		if((num[mp[1][i]]+num[mp[2][i]])%n!=num[mp[3][i]])
    			if((num[mp[1][i]]+num[mp[2][i]]+1)%n!=num[mp[3][i]])
    				return 0;
    	}
    	return 1;
    }
    inline void dfs(int now)
    {
    	if(now>n){
    		judge();return;
    	}
    	for(int i=n-1;i>=0;--i){
    		if(use[i]) continue;
    		num[q[now]+'A']=i;
    		if(can()){
    			use[i]=1;
    			dfs(now+1);
    			use[i]=0;
    		}
    	}
    	num[q[now]+'A']=-1;
    }
    int main()
    {
    	n=read();
    	memset(num,-1,sizeof(num));
    	for(int i=1;i<=3;++i) scanf("%s",mp[i]+1);
    	for(int i=n;i>=1;--i){
    		if(!v[mp[1][i]-'A']) q[++cnt]=mp[1][i]-'A',v[mp[1][i]-'A']=1;
    		if(!v[mp[2][i]-'A']) q[++cnt]=mp[2][i]-'A',v[mp[2][i]-'A']=1;
    		if(!v[mp[3][i]-'A']) q[++cnt]=mp[3][i]-'A',v[mp[3][i]-'A']=1;
     	}
    	dfs(1);
    	return 0;
    }
    
  • 相关阅读:
    mysql存储过程之游标
    ip后面带端口号如何做域名解析
    将博客搬至CSDN
    java微信公众号JSAPI支付以及所遇到的坑
    button元素的id与onclick的函数名字相同 导致方法失效的问题
    在centOS使用systemctl配置启动多个tomcat
    mysql正则表达式,实现多个字段匹配多个like模糊查询
    web前端基础知识-(二)CSS基本操作
    web前端基础知识-(一)html基本操作
    python学习笔记-(十六)python操作mysql
  • 原文地址:https://www.cnblogs.com/DarkValkyrie/p/11862659.html
Copyright © 2011-2022 走看看