poj 1753 dfs递归组合数

来源:互联网 发布:亳州淘宝店转让网 编辑:程序博客网 时间:2024/06/01 08:59

背景:一共16个棋子,每个棋子只有翻或者不翻两种情况,共有2^16种可以直接枚举。枚举的方法是组合数:C(16,k) (k:1 to 16) 就是翻1个,2个,3个.....16个的情况。其中用到了递归求组合数的思想。这种求组合数的方法和平常的思维不一样,比如求:1,2,3,4 的组合数,平常是先求一个数的:1,2,3,4四种情况,再求两个数的:12,13,14,23,24,34六种情况,再求三个数的:123,124,234三种情况,再求四个数的1234。而这个递归是dfs的方法:求1,12,123,1234,124,134,14,2,234.....对每个数开头的枚举玩。

自己写的求n个数中所有组合数的方法:

#include<map>#include<set>#include<stack>#include<queue>#include<vector>#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>#include<algorithm>#define M 200009#define INF 100000000#define LL long long intusing namespace std;int str[M],n;void dfs(int x){     str[x]=1;     for(int i=0;i < n;i++) if(str[i]) printf("%d ",i);     printf("\n");     for(int i=x+1;i < n;i++) dfs(i);     str[x]=0;     return;}int main(void){    while(~scanf("%d",&n)){        memset(str,0,sizeof(str));        for(int i=0;i < n;i++) dfs(i);    }    return 0;}
输入:6输出:11 21 2 31 2 3 41 2 3 4 51 2 3 4 5 61 2 3 4 61 2 3 51 2 3 5 61 2 3 61 2 41 2 4 51 2 4 5 61 2 4 61 2 51 2 5 61 2 61 31 3 41 3 4 51 3 4 5 61 3 4 61 3 51 3 5 61 3 61 41 4 51 4 5 61 4 61 51 5 61 622 32 3 42 3 4 52 3 4 5 62 3 4 62 3 52 3 5 62 3 62 42 4 52 4 5 62 4 62 52 5 62 633 43 4 53 4 5 63 4 63 53 5 63 644 54 5 64 655 66

2.以前学的递归实现全排列的代码,竟然忘了。核心是递归思想:对于长度为n的排列它的全排列等于第一个数分别和剩下的n-1个数交换,然后加上剩下n-1个数的全排列。这样一直到,只有一个全排列是排列就是它本身。

#include<map>#include<set>#include<stack>#include<queue>#include<vector>#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>#include<algorithm>#define M 200009#define INF 100000000#define LL long long intusing namespace std;int str[M],n;void sw(int &a,int &b){    if(a != b){    //异或要特判a == b的情况,要不然就是0        a=a^b;        b=a^b;        a=a^b;    }}void print(void){for(int i=1;i <= n;i++) printf("%d ",str[i]);printf("\n");}void permutation(int x){     if(x == n){ print();return;}     for(int i=x;i <= n;i++){        sw(str[x],str[i]);        permutation(x+1);        sw(str[x],str[i]);     }     return;}int main(void){    while(~scanf("%d",&n)){        for(int i=1;i <= n;i++) str[i]=i;        permutation(1);    }    return 0;}


本题代码:

//poj 1753#include<map>#include<set>#include<stack>#include<queue>#include<vector>#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>#include<algorithm>#define M 1009#define INF 100000000#define LL long long intusing namespace std;int str[16],ans,over,str1[16];bool check(void){     int x=0;     for(int i=0;i < 16;i++) x+=str[i];     if(x == 16 || !x) return true;     else return false;}void deal(int s){     str[s]=!str[s];     if(s-4 >= 0) str[s-4]=!str[s-4];     if(s+4 < 16) str[s+4]=!str[s+4];     if(s%4-1 >= 0) str[s-1]=!str[s-1];     if(s%4+1 <= 3) str[s+1]=!str[s+1];}void dfs(int s){     //for(int i=0;i < 16;i++) printf("%d ",str[i]);     //printf("\n ans is : %d\n",ans);     deal(s);     if(check())         if(ans < over) over =ans;     ans++;     for(int i=s+1;i < 16;i++){            dfs(i);     }     ans--;     deal(s);     return;}int main(void){    char temp;    while(~scanf("%c",&temp)){        int ci=0;        str[ci++]=(temp != 'b');        for(int i=1;i <= 4;i++){            for(int j=1;j <= 4;j++){                if(i == 1 && j == 1) continue;                temp=getchar();                str[ci++]=(temp != 'b');            }            getchar();        }        memcpy(str1,str,sizeof(str1));        over=INF;        for(int i=0;i < 16;i++){            ans=0;            if(check()) if(ans < over) over=ans;            ans++;            dfs(i);            memcpy(str,str1,sizeof(str1));        }        if(over < INF) printf("%d\n",over);        else printf("Impossible\n");    }    return 0;}


0 0
原创粉丝点击