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

原文地址:https://www.cnblogs.com/firstrate/p/3546358.html