zoukankan      html  css  js  c++  java
  • CSDN 高校俱乐部: 排列搜索

    CSDN 高校俱乐部/英雄会 题目;

    设数组a包含n个元素恰好是0..n - 1的一个排列,给定b[0],b[1],b[2],b[3]问有多少个0..n-1的排列a,满足(a[a[b[0]]]*b[0]+a[a[b[1]]]*b[1]+a[a[b[2]]]*b[2]+a[a[b[3]]]*b[3])%n==k ?

    输入包含5个参数:N,K,B0,B1,B2,B3,其中 4<= N<12, 0 <= K,B0,B1,B2,B3 < N

    单全排列超时代码:

    #include <stdio.h>
    #include <string.h>
    int b[5];
    int c[5];
    int a[15];
    int aa[15];
    int vis[15];
    int n, sum, k;
    
    int B_same_num(int b[]){
    	int i, j;
    	int p = 4;
    	for(i=0;i<3;++i){
    		if(b[i] == -1) continue;
    		for(j=i+1;j<4;++j)
    			if(b[i] == b[j]){
    				b[j] = -1;
    				--p;
    			}
    	}
    	return p;
    }
    
    void reset(int b[]){
    	int i, j;
    	for(i=j=0; j < 4; ++j){
    		if(b[j] != -1)
    			c[i++] = b[j];
    	}
    }
    
    void dfs(int s, int num) {
        int i;
        if(s == n) {
            if(4 == num)
            	if( (c[0]*a[a[0]] + c[1]*a[a[1]] + c[2]*a[a[2]] + c[3]*a[a[3]])%n == k )
            		++sum;
            if(3 == num)
            	if( (c[0]*a[0] + c[1]*a[1] + 2 * c[2]*a[2])%n == k )
            		++sum;
            if(2 == num)
            	if( (c[0]*a[0] + 3 * c[1]*a[1])%n == k )
            		++sum;
            if(1 == num)
            	if( (4 * c[0]*a[0])%n == k )
            		++sum;
    
    
            return;
        }
        for(i = 0; i < n; i++) {
            if(vis[i]) continue;
            vis[i] = 1;   
            a[s] = i;  
            dfs(s+1, num);      
            vis[i] = 0;   
        }
    }
    
    int main(int argc, char const *argv[])
    {
    	int t, i;
    	scanf("%d", &t);
    	while(t--){
    		sum = 0;
    		scanf("%d %d", &n, &k);
    		for(i=0;i<4;++i)
    			scanf("%d", &b[i]);
    		int num = B_same_num(b);
    		reset(b);
    		dfs(0, num);
    		printf("%d
    ", sum);
    	}
    	return 0;
    }
    

      

    双全排列改进后AC的代码:

    #include <stdio.h>
    #include <string.h>
    int b[5];
    int c[5];
    int a[15];
    int d[15];
    int sui[15];
    int vis[15];
    int vis1[15];
    int arr[15];
    int jiecheng[20];
    int n, sum, k;
    
    void _jiecheng(){
        jiecheng[0] =1;
        jiecheng[1] =1; 
        jiecheng[2] =2;
        jiecheng[3] =6; 
        jiecheng[4] =24; 
        jiecheng[5] =120; 
        jiecheng[6] =720;
        jiecheng[7] =5040;
        jiecheng[8] =40320;
        jiecheng[9] =362880;
        jiecheng[10] =3628800;
        jiecheng[11] =39916800;
        jiecheng[12] =479001600;
    }
    
    void init(){
        int i;
        for(i=0;i<15;++i) arr[i] = 0;
    }
    
    int B_same_num(int b[]){
    	int i, j;
    	int p = 4;
    	for(i=0;i<3;++i){
    		if(b[i] == -1) continue;
    		for(j=i+1;j<4;++j)
    			if(b[i] == b[j]){
    				b[j] = -1;
    				--p;
    			}
    	}
    	return p;
    }
    
    void reset(int b[]){
    	int i, j;
    	for(i=j=0; j < 4; ++j){
    		if(b[j] != -1)
    			c[i++] = b[j];
    	}
    }
    
    void suiji(int s, int num, int b_num) {
        int i, j;
        int dd;
        dd = n - num - b_num;
    
        if(s == num) {
            j=0;
            for(i = 0; i < b_num; i++){
                if(arr[a[c[i]]] == 1) continue;
                else {
                    a[a[c[i]]] = sui[j++];
                }
            }
            if(4 == b_num){
                if( (c[0]*a[a[c[0]]] + c[1]*a[a[c[1]]] + c[2]*a[a[c[2]]] + c[3]*a[a[c[3]]])%n == k ){
                    sum+=jiecheng[dd];
                }
            }
            if(3 == b_num)
                if( (c[0]*a[a[c[0]]] + c[1]*a[a[c[1]]] + 2 * c[2]*a[a[c[2]]])%n == k )
                    sum+=jiecheng[dd];
            if(2 == b_num)
                if( (c[0]*a[a[c[0]]] + 3 * c[1]*a[a[c[1]]])%n == k )
                    sum+=jiecheng[dd];
            if(1 == b_num)
                if( (4 * c[0]*a[a[c[0]]])%n == k )
                   sum+=jiecheng[dd];
            return;
        }
        for(i = 0; i < n; i++) {
            if(vis1[i]) continue;
            if(vis[i]) continue;
            vis1[i] = 1;   
            sui[s] = i;     
            // printf("sui : %d
    ", sui[s]);
            suiji(s+1, num, b_num);      
            vis1[i] = 0;   
        }
    }
    
    int arr_num(int num){
        int dd = 0;
        int i;
        for(i=0;i<num;++i)
            if(arr[a[c[i]]] == 1) continue;
            else ++dd;
        return dd;
    }
    
    
    void dfs(int s, int num) {
        int i, t;
        if(s == num) {
            init();
            for(i=0;i<num;++i){
                a[c[i]] = d[i];
                arr[c[i]] = 1;
            }
            t = arr_num(num);
            suiji(0, t, num);
            return;
        }
        for(i = 0; i < n; i++) {
            if(vis[i]) continue;
            vis[i] = 1;   
            d[s] = i;  
            dfs(s+1, num);      
            vis[i] = 0;   
        }
    }
    
    int main(int argc, char const *argv[])
    {
    	int t, i;
    	scanf("%d", &t);
    	while(t--){
    		sum = 0;
            _jiecheng();
    		scanf("%d %d", &n, &k);
    		for(i=0;i<4;++i)
    			scanf("%d", &b[i]);
    		int num = B_same_num(b);
    		reset(b);
    		dfs(0, num);
    		printf("%d
    ", sum);
    	}
    	return 0;
    }
    

      

    精简版 代码:

    #include <stdio.h>
    #include <string.h>
    
    int a[12];
    int b[4];
    int N, K, ans;
    int v[12];
    int fac[14];
    
    void factorial(){
    	int i;
        fac[0] = 1;
    	for(i=1;i<=12;++i) 
    		fac[i] = fac[i-1]*i;
    }
    
    void dfs2(int s){
    	int t;
    	if(s == 4){
    		if ((a[a[b[0]]]*b[0]+a[a[b[1]]]*b[1]+a[a[b[2]]]*b[2]+a[a[b[3]]]*b[3])%N==K){
    			t = 0;
    			int i;
    			for(i=0;i<N;++i)
    				if(a[i] == -1) ++t;
    			ans += fac[t];
    		}
    		return;
    	}
        if(a[a[b[s]]] != -1)
        	dfs2(s+1);
        else{
        	int i;
        	for(i=0;i<N;++i)
        		if(!v[i]){
        			v[i] = 1;
        			a[a[b[s]]] = i;
        			dfs2(s+1);
        			v[i] = 0;
        			a[a[b[s]]] = -1;
        		}
        }
    }
    
    void dfs(int s){
    	int i;
    	if(s == 4){
    		dfs2(0);
    		return;
    	}
    	if(a[b[s]] != -1)
    		dfs(s+1);
    	else{
    		for(i=0;i<N;++i)
    			if(!v[i]){
    				v[i] = 1;
    				a[b[s]] = i;
    				dfs(s+1);
    				v[i] = 0;
    				a[b[s]] = -1;
    			}
    	}
    }
    
    int main(int argc, char const *argv[])
    {
    	int i;
    	scanf("%d%d%d%d%d%d", &N, &K, &b[0], &b[1], &b[2], &b[3]);
    	ans = 0;
    	memset(v, 0, sizeof(v));
    	for(i=0;i<12;++i) a[i] = -1;
    	factorial();
    	dfs(0);
    	printf("%d
    ", ans);
    	return 0;
    }
    

      

      

    测试数据 :

    #include <stdio.h>
    #include <string.h>
    
    int howmany (int N,int K,int B0,int B1,int B2,int B3)
    {
       if(N==4 && K==0 && B0==3 && B1==2 &&B2==1 &&B3==0) return 4;
       if(N==5 && K==2 && B0==1 && B1==2 &&B2==3 &&B3==4) return 40;
       if(N==6 && K==4 && B0==5 && B1==4 &&B2==3 &&B3==2) return 78;
       if(N==7 && K==6 && B0==6 && B1==4 &&B2==2 &&B3==0) return 684;
       if(N==8 && K==1 && B0==0 && B1==1 &&B2==2 &&B3==3) return 5454;
       if(N==9 && K==3 && B0==4 && B1==8 &&B2==1 &&B3==2) return 44028;
       if(N==10 && K==5 && B0==3 && B1==7 &&B2==9 &&B3==0) return 349776;
       if(N==11 && K==7 && B0==3 && B1==1 &&B2==8 &&B3==9) return 3651984;
       if(N==11 && K==0 && B0==0 && B1==0 &&B2==0 &&B3==0) return 39916800;
       if(N==11 && K==5 && B0==4 && B1==3 &&B2==2 &&B3==1) return 3662976;
       return 0;
    }
    

      

    PS :  和别人的代码根本无法媲美。。以后在重新改进一下这份代码!

  • 相关阅读:
    CodeForces gym Nasta Rabbara lct
    bzoj 4025 二分图 lct
    CodeForces 785E Anton and Permutation
    bzoj 3669 魔法森林
    模板汇总——快读 fread
    bzoj2049 Cave 洞穴勘测 lct
    bzoj 2002 弹飞绵羊 lct裸题
    HDU 6394 Tree 分块 || lct
    HDU 6364 Ringland
    nyoj221_Tree_subsequent_traversal
  • 原文地址:https://www.cnblogs.com/firstrate/p/3546358.html
Copyright © 2011-2022 走看看