• 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;
    }
    
  • 相关阅读:
    WCF客户端链接服务超时客户端close
    C# byte数组常用扩展浅析(转)
    代码生成相关工具及技术
    已处理证书链,但是在不受信任提供程序信任的根证书中终止。
    清理SQL Server数据库日志的两种方法
    开源框架项目列表
    SQL Server数据库文件恢复技术
    VS2008找不到导出模板
    jquery 学习笔记(二)
    方法的参数的默认值设置
  • 原文地址:https://www.cnblogs.com/DarkValkyrie/p/11862659.html
Copyright © 2020-2023  润新知