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;
    }
    
  • 相关阅读:
    perl学习笔记之:正则表达式
    POJ 3436 ACM Computer Factory (拆点+输出解)
    POJ 3436 ACM Computer Factory (拆点+输出解)
    POJ 1637 Sightseeing tour ★混合图欧拉回路
    POJ 1637 Sightseeing tour ★混合图欧拉回路
    POJ 1149 PIGS ★(经典网络流构图)
    POJ 1149 PIGS ★(经典网络流构图)
    HDU 4571 Travel in time ★(2013 ACM/ICPC长沙邀请赛)
    HDU 4571 Travel in time ★(2013 ACM/ICPC长沙邀请赛)
    UPC 2224 Boring Counting ★(山东省第四届ACM程序设计竞赛 tag:线段树)
  • 原文地址:https://www.cnblogs.com/DarkValkyrie/p/11862659.html
Copyright © 2011-2022 走看看