• 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 :  和别人的代码根本无法媲美。。以后在重新改进一下这份代码!

  • 相关阅读:
    Android4.2以及最新SDK的尝鲜使用
    UVA 1524
    StringTokenizer类的使用
    Tuxedo入门学习
    ReviewBoard安装和配置札记
    一步一步写算法(之单向链表)
    腾讯2014年实习生招聘笔试面试经历
    二路单调自增子序列模型【acdream 1216】
    [置顶] c# 验证码生成
    Android Service 服务(一)—— Service
  • 原文地址:https://www.cnblogs.com/firstrate/p/3546358.html
Copyright © 2020-2023  润新知