• uva 11668 How Many Teams?


    Sample Input                                     Output for Sample Input

    3
    2 2
    sohelH-CSE samee-CSE
    4 2
    Blind-ECS sidky-CSE muntasir-CSC ShadowCoder-EEE
    4 2

    ABC-D1 DEF-D1 ghi-D2 jkl-D3

    Case 1: 0
    Case 2: 24
    Case 3: 16


    题意:给出n个人与这些人分别所属的公司,其中属于同一家公司的人不会超过3个人。将n个人任意排列(即有n!)中情况,按顺序将任意排列的n个人,每k个人一组(保证n%k==0),问满足每组不会有相同公司人的排列有多少个?

    比赛的时候一直没往DP方面想,后来发现确实是一个很少见的dp或者是以前不知到的dp,想出了状态转移到是挺好想的了。

    状态最后是间接经过肖神提示得到的,dp[i][j][p]表示还剩i个公司有3个人,j个公司有2个人,p个公司有1个人,的情况有多少种。

    首先,最终要求的肯定就是dp[0][0][0]肯定很容易想了;初始值就是dp[x][y][z]=1,x,y,z就是给的情况

    其次如果将i,j,p逆着递推,这样就正好得到最终结果,dp[i][j][p]可以有很多中转移情况,应为组成新的一组需要k个人,而这k个人是从i,j,p那一快转移过来都有可能,所以实现预处理好所以情况,到时候一一枚举就可以了;

    最后转移的过程有很多排列数和组合数有区别的地方要注意,例如从i个人中如果要选ti个人,那么就会有C(i,ti)*(3^ti)种情况,对于j,p同理,最后选出来的k个人,同样也还是要有一种顺序而言,所以又是k!,写的过程中注意及时取模就ok了。

    另外输入其实也看起来处理挺麻烦的,但其实可以用string中的substr,和find函数,然后就挺好写了。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<map>
     7 #define see(x) cout<<#x<<":"<<x<<endl;
     8 using namespace std;
     9 const int maxn = 105;
    10 const int mod = 1234;
    11 int dp[maxn][maxn][maxn], cntt[maxn], c[maxn][maxn], way[maxn][5];
    12 int exp22[maxn], exp3[maxn], f[maxn];
    13 string str, tmp;
    14 map<string,int> cha;
    15 int main(){
    16     int t, i, j, p, l, m, cas=1, n, k, cnt, ti, tj, tp;
    17     int x, y, z;
    18     c[0][0]=1;
    19     for(i=1;i<maxn;i++){
    20         c[i][0] = 1;
    21         for(j=1;j<=i;j++){
    22             c[i][j] = (c[i-1][j-1]+c[i-1][j])%mod;
    23         }
    24     }
    25     exp22[0] = exp3[0] = f[0] = 1;
    26     for(i=1;i<maxn;i++){
    27         exp22[i] = (exp22[i-1]*2)%mod;
    28         exp3[i] = (exp3[i-1]*3)%mod;
    29         f[i] = (f[i-1]*i)%mod;
    30     }
    31     scanf("%d",&t);
    32     while(t--){
    33         scanf("%d%d",&n,&k);
    34         m = 0;
    35         for(i=0;i<=k;i++){
    36             for(j=0;j<=k;j++){
    37                 for(p=0;p<=k;p++){
    38                     if((i+j+p)==k){
    39                         way[m][1] = i;
    40                         way[m][2] = j;
    41                         way[m][3] = p;
    42                         m++;
    43                     }
    44                 }
    45             }
    46         }
    47         cha.clear();
    48         cnt=0;
    49         memset(cntt,0,sizeof(cntt));
    50         x=y=z=0;
    51         for(i=0;i<n;i++){
    52             cin>>str;
    53             p = str.find('-');
    54             tmp = str.substr(p+1,str.size()-p-1);
    55             if(!cha[tmp]){
    56                 cha[tmp] = ++cnt;
    57                 cntt[cnt]++;
    58             }
    59             else{
    60                 cntt[cha[tmp]]++;
    61                 if(cntt[cha[tmp]]==3){
    62                     z++;
    63                 }
    64             }
    65             y = n-z*2-cnt;
    66             x = cnt-z-y;
    67         }
    68         memset(dp,0,sizeof(dp));
    69         dp[z][y][x] = 1;
    70         for(i=n;i>=0;i--){
    71             for(j=n;j>=0;j--){
    72                 for(p=n;p>=0;p--){
    73                     if(dp[i][j][p]){
    74                         for(l=0;l<m;l++){
    75                             ti = way[l][1]; tj = way[l][2]; tp = way[l][3];
    76                             if(i>=ti&&j>=tj&&p>=tp){
    77                                 dp[i-ti][j+ti-tj][p+tj-tp] += dp[i][j][p]*c[i][ti]%mod*exp3[ti]%mod*c[j][tj]%mod*exp22[tj]%mod*c[p][tp]%mod*f[k]%mod;
    78                                 dp[i-ti][j+ti-tj][p+tj-tp] %= mod;
    79                             }
    80                         }
    81                     }
    82                 }
    83             }
    84         }
    85         printf("Case %d: %d\n",cas++,dp[0][0][0]);
    86     }
    87     return 0;
    88 }
  • 相关阅读:
    匈牙利算法——S.B.S.
    洛谷P1328 生活大爆炸版石头剪刀布——S.B.S.
    洛谷P1101 单词方阵——S.B.S.
    noip2010提高组3题题解 by rLq
    洛谷P1605 迷宫——S.B.S.
    yii2.0 curd操作
    我常用的linux命令
    常用css
    ln 软链
    crontab下git命令无效
  • 原文地址:https://www.cnblogs.com/celia01/p/2645757.html
Copyright © 2020-2023  润新知