DFS专题--Hand in hand

来源:互联网 发布:xquartz mac教程 编辑:程序博客网 时间:2024/05/16 07:03

A - Hand in hand
Time Limit: 10000/5000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others)
Submit Status
Problem Description

  There are a lots of ACMers in ACdream Kingdom. They usually play a interesting(?) game called hand in hand, which can show their friendship.

Now you invites n-1 friends to play this game with you. Everyone of these n peoples has two hands (No one is disabled) and each hand of a person has a number on it.
Two friends can hand in hand if and only if the numbers of two hands from two friends are coprime. (Two numbers are coprime if and only if the greatest common divisor is 1.)
So could you tell me how many ways can you and your friends become a ring?
Remember, the left hand can only hand in hand with the right hand of other people and every one faces to the ring inside, or it seems stupid.
Remember again, all of these n people must participate in this interesting game.
Remember again and again, if the indexs of the people of two rings can be written as the same order when we cut the rings from some place, these two rings can be considered the same.
For example:
if there are 4 people and the numbers written in their hands are 1 5,2 4,3 5,6 4 (first number is left hand, second is right hand)
5 1-4 2 4 2-5 3 5 1-4 6
| | is the same as | | but is different from | | .
6 4-3 5 1 5-6 4 2 4-3 5
Input

Multiple case, please calculate until EndOfFile.
For each case, it begins with a positive integer n(1<=n<=11), which indicates the number of players.
Then following n lines, and every lines is a pair of positive integers. The first number of the i-th line is the number on the left hand of the i-th person , and the second one is the number on the right hand of the i-th person. Both of the integers are less than 50.
Output

For each case, please output an integer, indicated the number W of ways to hand in hand.
Sample Input

2
1 3
2 6
3
1 2
2 3
3 4
4
1 5
2 4
3 5
6 4
Sample Output

1
0
2
Hint

For the first case, only one way can you two become a ring.
1-6
3-2
For the second case, because the second person’s left hand has a number ‘2’ on it, (s)he can not find any right hands to hand in hand. Therefore just output 0.
For the third case, the two orders described in the description are both OK.

题目大意: n个人,每个人左手右手各有一个数字,围成圈,拉着的两只手的数字要求互质,求情况总数。

分析: 两种解法。一、由于是围成一个圈,所以,先固定一个人的位置,对另外n-1个人进行全排列,判断是否互质。二、DFS搜。
注意,n=1时,答案为0。T^T….没考虑这个,找了半天没找出错误….

代码:

//方法一、next_permutation#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int l[15], r[15], p[15], g[55][55];int n, ans;int gcd(int a, int b) { return b == 0 ? a : gcd(b, a%b); }void lalala() {    for(int i = 0; i < n; i++)        if(!g[r[p[i]]][l[p[i+1]]]) return;    ans++;    return;}int main() {    for(int i = 1; i < 51; i++)        for(int j = 1; j < 51; j++) {            g[i][j] = (gcd(max(i, j), min(i, j)) == 1);        }    while(scanf("%d", &n) != EOF) {        ans = 0;        for(int i = 0; i < n; i++) {            scanf("%d%d", &l[i], &r[i]);            p[i] = i;            if(i == 0) l[n] = l[0], r[n] = r[0];        }        if(n == 1) {;}        else {            do{                lalala();            }while(next_permutation(p+1, p+n));        }        printf("%d\n", ans);    }    return 0;}
//方法二、DFS#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int n, a[15], b[15];int ans, cnt, vis[15];int gcd(int a, int b) { return b == 0 ? a : gcd(b, a%b); }void dfs(int x) {    if(cnt == n) {        if(gcd(max(a[0], b[x]), min(a[0], b[x])) == 1)            ans++;        return;    }    for(int i = 1; i < n; i++) {        if(!vis[i] && gcd(max(b[x], a[i]), min(b[x], a[i])) == 1) {            cnt++;            vis[i] = 1;            dfs(i);            vis[i] = 0;            cnt--;        }    }    return;}int main() {    while(scanf("%d", &n) != EOF) {        for(int i = 0; i < n; i++)            scanf("%d%d", &a[i], &b[i]);        memset(vis, 0, sizeof(vis));        ans = 0;        cnt = 1;        vis[0] = 1;        dfs(0);        if(n == 1) printf("0\n");        else printf("%d\n", ans);    }    return 0;}
0 0
原创粉丝点击