【容斥+java】SGU 476 Coach's Trouble

通道

题意:有3*n个人,分成n组,每组三个人。给出k个三元组,这三个人不可组队,问最后可以组队的总方案数

思路:

当k=0时,有(C[3*n][3]*C[3*n-3][3]*……*C[3][3])/n!种方案,展开以后可以得到dp[n]=(3*n)!/n!/6^n。

显然可以写成递推式:dp[n]=dp[n-1]*(3*n-1)*(3*n-2)/2。

那么容斥一下,答案=总方案数-至少含一个禁止组合的+至少含两个禁止组合的-……

二进制暴力TLE了。DFS的话会有很多剪枝,当前几个已经出现冲突,自然不会再往后面搜了

代码:

import java.util.*;
import java.math.*;

public class Solution {
    static int group[][] = new int[25][3];
    static int cnt[] = new int[25];
    static boolean vis[] = new boolean[3001];
    static int n, k, depth;

    static void Init() {
        for (int i = 0; i < 25; i++)
            cnt[i] = 0;
        for (int i = 0; i < 3001; i++)
            vis[i] = false;
    }

    static void DFS(int index, int now) {
        if (now == depth) {
            if (depth % 2 == 1)
                cnt[depth]++;
            else
                cnt[depth]--;
        } else {
            for (int i = index; i < k; i++) {
                if (vis[group[i][0]] == false && vis[group[i][1]] == false
                        && vis[group[i][2]] == false) {
                    vis[group[i][0]] = vis[group[i][1]] = vis[group[i][2]] = true;
                    DFS(i + 1, now + 1);
                    vis[group[i][0]] = vis[group[i][1]] = vis[group[i][2]] = false;
                }
            }
        }
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        BigInteger dp[] = new BigInteger[1001];
        BigInteger res;
        dp[0] = dp[1] = BigInteger.ONE;
        for (int i = 2; i < 1001; i++)
            dp[i] = dp[i - 1].multiply(BigInteger.valueOf(3 * i - 1))
                    .multiply(BigInteger.valueOf(3 * i - 2))
                    .divide(BigInteger.valueOf(2));
        while (in.hasNext()) {
            Init();
            n = in.nextInt();
            k = in.nextInt();
            for (int i = 0; i < k; i++) 
                for (int j = 0; j < 3; j++)
                    group[i][j] = in.nextInt();
            for (depth = 1; depth <= k; depth++)
                DFS(0, 0);
            res = BigInteger.ZERO;
            for (int i = 1; i <= k; i++) 
                if (cnt[i] != 0)
                    res = res.add(dp[n - i].multiply(BigInteger.valueOf(cnt[i])));
            System.out.println(dp[n].subtract(res));
        }
    }
}
View Code

 

posted @ 2015-08-19 22:49  mithrilhan  阅读(141)  评论(0编辑  收藏  举报