BZOJ4321: queue2

本文介绍了一种使用动态规划的方法来解决人员安排中的冲突问题。通过定义状态f[0/1][i][j],表示第i个人时有j对冲突的情况,进一步考虑与前一个人的关系,最终求得在没有冲突的情况下人员安排的方案数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题面

传送门

Sol

先设一个套路的状态: f[i][j] f [ i ] [ j ] 表示到第 i i 个人,有j对冲突
但是我们不能确定 i1 i − 1 ,所以不好决策i的位置
所以再加一维 0/1 0 / 1 f[0/1][i][j] f [ 0 / 1 ] [ i ] [ j ] 表示 i i i1是否有冲突
每枚举一个人,我们就要把它插入到之前的队列中
转移:
f[0][i][j] f [ 0 ] [ i ] [ j ]

乘上 j j ,转移给f[0][i+1][j1],表示消除一个冲突
乘上 i+1j2 i + 1 − j − 2 ,转移给 f[0][i+1][j] f [ 0 ] [ i + 1 ] [ j ] ,表示不消除冲突,并且在剩下的 i+1j i + 1 − j 选一个不与 i i 相邻的位置插入i+1,所以减去 2 2
乘上2:转移给 f[1][i+1][j+1] f [ 1 ] [ i + 1 ] [ j + 1 ] ,即选一个与 i i 相邻的位置插入i+1

f[1][i][j] f [ 1 ] [ i ] [ j ] :类似,四种情况自己 yy y y 去吧

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int Zsy(7777777);

IL ll Input(){
    RG ll x = 0, z = 1; RG char c = getchar();
    for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
    for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
    return x * z;
}

int n, f[2][1005][1005];

IL void Up(RG int &x, RG int y){
    x += y;
    if(x >= Zsy) x -= Zsy;
}

int main(RG int argc, RG char* argv[]){
    n = Input();
    f[0][1][0] = 1;
    for(RG int i = 1; i < n; ++i)
        for(RG int j = 0; j < i; ++j){
            if(f[0][i][j]){
                if(j) Up(f[0][i + 1][j - 1], 1LL * f[0][i][j] * j % Zsy);
                if(i - j - 1 > 0) Up(f[0][i + 1][j], 1LL * f[0][i][j] * (i - j - 1) % Zsy);
                Up(f[1][i + 1][j + 1], 1LL * f[0][i][j] * 2 % Zsy);
            }
            if(f[1][i][j]){
                Up(f[1][i + 1][j], f[1][i][j]);
                Up(f[1][i + 1][j + 1], f[1][i][j]);
                if(j > 1) Up(f[0][i + 1][j - 1], 1LL * f[1][i][j] * (j - 1) % Zsy);
                if(i - j > 0) Up(f[0][i + 1][j], 1LL * f[1][i][j] * (i - j) % Zsy);
            }
        }
    printf("%d\n", f[0][n][0]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值