vijos - P1286座位安排 (DP状态压缩 + 组合数 + python)

P1286座位安排

Accepted

标签:[显示标签]

背景

快要期中考试了!老师需要hzy帮他排考试的座位。。。

描述

考场里的座位恰好有n行m列,并且恰好有n*m位考生在这个考场里面考试,也就是说,所有的座位上都有考生。hzy根据学校记载,有k位考生可能作弊,因此hzy不能让他们之中的任何两个人做在相邻的座位上!所谓相邻的座位,即在同一行相邻列或者在同一列的相邻行的座位。hzy准备这样安排座位,首先随机选择一种方案,如果这种方案是合法的,就用这种方案,否则重新选择。你的任务是计算,他得到一个合法方案时,需要的期望选择次数。

格式

输入格式

输入文件为一行,仅包含三个整数n,m和k。

输出格式

如果不存在合法的方案,则输出文件seating.out中应该包含Impossible!,否则输出一个分数p/q,表示期望选择次数(即平均次数),这里p和q应该是互质的。

样例1

样例输入1[复制]

1 4 3

样例输出1[复制]

Impossible!

样例2

样例输入2[复制]

2 3 2

样例输出2[复制]

15/8

提示

1≤n≤80,1≤m≤80,1≤n*m≤80

0≤k≤20,并且k≤n*m

对于题目状态压缩很明显,然后是对于组合数,组合数是我的弱点,高中知识基本都忘得差不多了

提示一下:C(m,n) = n!/(m! * (n - m)!)  -> n*(n-1)*(n-2)....(n-m+1)/m!(这里的k比较小,所以这么转换,如果是n-m比较小则可以转换为:n*(n-1)*(n-2).....*(m+1)/(n-m)!)

如此其他的就是状态压缩的过程了

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long LL;
LL dp[80 + 5][20 + 5][1 << 12];
int n, m, k;

LL gcd(LL a,LL b) {
    return b? gcd(b, a % b) : a;
}

bool C(int mm,int s) {
    for(int i = 0; i < 15; i ++) {
        if((s & (1 << i)) && (mm & (1 << i))) return false;
    }
    return true;
}
bool CC(int s) {
    int bits[15] = {0},cnt = 0;
    while(s) {
        bits[cnt ++] = (s & 1);
        s >>= 1;
    }
    for(int i = 1; i < cnt; i ++) {
        if(bits[i] + bits[i - 1] >= 2)return false;
    }
    return true;
}
LL CS(LL c, LL s) {
    LL ret = 1;
    for(int i = 1; i <= s; i ++) ret = ret * (c - i + 1) / i;
    return ret;
}
void CSS(LL nn,LL kk,LL x) {
    LL xi = 1,sh = 1,f;
    for(int i = 1; i <= kk; i ++) xi *= i;
    for(int i = nn - kk + 1; i <= nn; i ++ ) {
        sh *= i;
        f = gcd(sh,xi);
        sh /= f;
        xi /= f;
    }
    xi *= x;
    f = gcd(xi,sh);
    xi /= f;
    sh /= f;
    printf("%I64d/%I64d\n",sh,xi);
}
int main() {
    scanf("%d%d%d", &n, &m, &k);
    if(m > n) swap(n, m);
    dp[0][0][0] = 1;//第几行安排了多少人了,以及此时要安装的人数
    for(int i = 1; i <= n; i ++) {
        for (int j = 0; j <= k; j ++) {
            for(int s = 0; s < (1 << m); s ++) {
                if(!CC(s)) continue;
                int bits = 0,ft = s;
                while(ft) {
                    bits += (ft & 1);
                    ft >>= 1;
                }
                for(int ks = 0 ; ks < (1 << m); ks ++) {
                    if(!CC(ks)) continue;
                    if(!C(ks,s)) continue;
                    if(j - bits < 0) continue;
                    dp[i][j][s] += dp[i - 1][j - bits][ks];
                }
            }
        }
    }
    LL ret = 0;
    for(int i = 0; i < (1 << m); i ++) {
        ret += dp[n][k][i];
    }
    if(ret <= 0) {
        printf("Impossible!\n");
    } else {
        CSS(n * m, k, ret);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-05 10:52:20

vijos - P1286座位安排 (DP状态压缩 + 组合数 + python)的相关文章

dp状态压缩

dp状态压缩 动态规划本来就很抽象,状态的设定和状态的转移都不好把握,而状态压缩的动态规划解决的就是那种状态很多,不容易用一般的方法表示的动态规划问题,这个就更加的难于把握了.难点在于以下几个方面:状态怎么压缩?压缩后怎么表示?怎么转移?是否具有最优子结构?是否满足后效性?涉及到一些位运算的操作,虽然比较抽象,但本质还是动态规划.找准动态规划几个方面的问题,深刻理解动态规划的原理,开动脑筋思考问题.这才是掌握动态规划的关键. 动态规划最关键的要处理的问题就是位运算的操作,容易出错,状态的设计也直

HDU 4336 Card Collector (期望DP+状态压缩 或者 状态压缩+容斥)

题意:有N(1<=N<=20)张卡片,每包中含有这些卡片的概率,每包至多一张卡片,可能没有卡片.求需要买多少包才能拿到所以的N张卡片,求次数的期望. 析:期望DP,是很容易看出来的,然后由于得到每张卡片的状态不知道,所以用状态压缩,dp[i] 表示这个状态时,要全部收齐卡片的期望. 由于有可能是什么也没有,所以我们要特殊判断一下.然后就和剩下的就简单了. 另一个方法就是状态压缩+容斥,同样每个状态表示收集的状态,由于每张卡都是独立,所以,每个卡片的期望就是1.0/p,然后要做的就是要去重,既然

uva 11367 dijkstra+dp状态压缩

题意:给出n个地点 和 每个地点的油价 ,有 m 条边 , 并给出每条边长度 .1单位汽油可以走1千米  , 油箱的容量为 c , 在初始点 s 时 , 油箱中的油为 0 , 求s 到 t 的最小花费 . 解法: 定义 状态 d[i][j] 表示到达 地点 i 且油箱中有 j 单位油时的最小 花费. 对于状态的转移时 , 有两种方法: 1.把每个点的所有状态都求出 2.不把每个点的状态都求出 , 而是一单位一单位的加油. 对于第一种方法 , 会超时 , 因为每个点的状态太多 , 但是能用的状态就

hdu 4352 数位dp + 状态压缩

XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2265    Accepted Submission(s): 927 Problem Description #define xhxj (Xin Hang senior sister(学姐)) If you do not know xhxj, then careful

HDU4352XHXJ&#39;s LIS(dp状态压缩)

XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 809    Accepted Submission(s): 308 Problem Description #define xhxj (Xin Hang senior sister(学姐)) If you do not know xhxj, then careful

【HDU 4352】 XHXJ&#39;s LIS (数位DP+状态压缩+LIS)

XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2422    Accepted Submission(s): 990 Problem Description #define xhxj (Xin Hang senior sister(学姐)) If you do not know xhxj, then careful

Uva 10817 Headmaster&#39;s Headache (DP+ 状态压缩)

Problem D: Headmaster's Headache Time limit: 2 seconds The headmaster of Spring Field School is considering employing some new teachers for certain subjects. There are a number of teachers applying for the posts. Each teacher is able to teach one or

[数位dp+状态压缩] hdu 4352 XHXJ&#39;s LIS

题意: 给x.y.k,在[x,y] 范围内最长上升子序列长度是k的数有几个 思路: 模仿 LIS nlogn的想法,这里就只有10个数,进行状压 然后直接搜就好了不用二分 然后按位dp下去就ok了! 代码: #include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"queue" #include"al

(hiho1048)POJ2411Mondriaan&#39;s Dream(DP+状态压缩 or 轮廓DP)

问题: Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series' (where he had to use his toilet paper to draw on, for all of his paper was filled with squares and rectangle