【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的话会有很多剪枝,当前几个已经出现冲突,自然不会再往后面搜了。

 1 import java.util.*;

 2 import java.math.*;

 3 

 4 public class Solution {

 5     static int group[][] = new int[25][3];

 6     static int cnt[] = new int[25];

 7     static boolean vis[] = new boolean[3001];

 8     static int n, k, depth;

 9 

10     static void Init() {

11         int i;

12         for (i = 0; i < 25; i++)

13             cnt[i] = 0;

14         for (i = 0; i < 3001; i++)

15             vis[i] = false;

16     }

17 

18     static void DFS(int index, int now) {

19         if (now == depth) {

20             if (depth % 2 == 1)

21                 cnt[depth]++;

22             else

23                 cnt[depth]--;

24         } else {

25             int i;

26             for (i = index; i < k; i++) {

27                 if (vis[group[i][0]] == false && vis[group[i][1]] == false

28                         && vis[group[i][2]] == false) {

29                     vis[group[i][0]] = vis[group[i][1]] = vis[group[i][2]] = true;

30                     DFS(i + 1, now + 1);

31                     vis[group[i][0]] = vis[group[i][1]] = vis[group[i][2]] = false;

32                 }

33             }

34         }

35     }

36 

37     public static void main(String[] args) {

38         Scanner in = new Scanner(System.in);

39         int i, j;

40         BigInteger dp[] = new BigInteger[1001];

41         BigInteger res;

42         dp[0] = dp[1] = BigInteger.ONE;

43         for (i = 2; i < 1001; i++)

44             dp[i] = dp[i - 1].multiply(BigInteger.valueOf(3 * i - 1))

45                     .multiply(BigInteger.valueOf(3 * i - 2))

46                     .divide(BigInteger.valueOf(2));

47         while (in.hasNext()) {

48             Init();

49             n = in.nextInt();

50             k = in.nextInt();

51             for (i = 0; i < k; i++) {

52                 for (j = 0; j < 3; j++)

53                     group[i][j] = in.nextInt();

54             }

55             for (depth = 1; depth <= k; depth++)

56                 DFS(0, 0);

57             res = BigInteger.ZERO;

58             for (i = 1; i <= k; i++) {

59                 if (cnt[i] != 0)

60                     res = res

61                             .add(dp[n - i].multiply(BigInteger.valueOf(cnt[i])));

62             }

63             System.out.println(dp[n].subtract(res));

64         }

65     }

66 }

你可能感兴趣的:(tr)