题意:有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 }
posted on 2012-09-07 12:22  DrunBee  阅读(327)  评论(0编辑  收藏  举报