ACDREAM 05A Hand in hand(DFS专场)

ACDREAM 05A Hand in hand

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(1~11)个人,每个人的左右手上都写了一个数字(<50),现在要求这n个人手拉手围成一圈,必须左手拉右手,右手拉左手(要不然很挫),而且要求牵在一起的两只手上的数字是互质的(最大公约数为1),问这n个人有多少种满足条件的牵手方式。(旋转和翻转算作同一种)
解题思路:首先先打一张50以内的互质表。然后我们将一个人的位置固定下来,这样可以防止重复计算(旋转和翻转),接着开始DFS(具体见代码)。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;
typedef long long ll;
struct peo{
    int L, R;
}p[55];
int vis[55];
int vis2[55][55];
int n, ans, beg;
int A[55][55];
void DFS(int pos, int cnt) {
    if (cnt == n - 1) {
        if (A[p[pos].R][p[0].L] == 1) { //因为是环,所以最后还需要判断能否和第一个人牵手
            ans++;
        }
        return;
    }
    for (int i = 0; i < n; i++) {
        if (!vis[i]) {
            if (A[p[pos].R][p[i].L] == 1) { //pos的右手是否可以牵i的左手
                vis[i] = 1;
                DFS(i, cnt + 1);
                vis[i] = 0;
            }
        }   
    }
}
int main() {
    memset(A, 0, sizeof(A));
    for (int i = 1; i <= 50; i++) { //打互质表
        for (int j = i; j <= 50; j++) {
            if (!A[i][j]) {
                if (__gcd(i, j) == 1) {
                    A[i][j] = A[j][i] = 1;
                }
            }
        }
    }
    while (scanf("%d", &n) != EOF) {
        memset(vis, 0, sizeof(vis));
        memset(vis2, 0, sizeof(vis2));
        for (int i = 0; i < n; i++) {
            scanf("%d %d", &p[i].L, &p[i].R);
        }
        if (n == 1) {
            printf("0\n");
            continue;
        }
        ans = 0;
        vis[0] = 1; //固定下一个人的位置
        DFS(0, 0);
        printf("%d\n", ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值