zoukankan      html  css  js  c++  java
  • B4321 queue2 dp

    这个题的dp真的恶心。首先,一开始我以为是一道数论题,但是组合数和这个题没啥关系。dp方程巨麻烦,状态是dp[i][j][0/1],代表i位连了j个,上一位是否连着。然后开始转移,证明如下:

    我们先来分析i-1,i相邻,也就是f[i][j][1]怎么推。
    对于i,i-1,i-2,有这几种关系,
    本来i-1与i-2相邻,将i插入两者中,拆了一对(i-1,i-2),又形成了一对(i-1,i),这样方案来源于f[i-1][j][1]。
    本来i-1与i-2相邻,将i插入与i-1相邻却不被i-1与i-2夹着,多形成了一对(i-1,i),这样方案来源于f[i-1][j-1][1]。
    本来i-1与i-2不相邻,将i插入与i-1相邻,形成了一对(i-1,i),这样方案来源于f[i-1][j-1][1],由于i-1的左右够可以插,方案就乘2。
    这样f[i][j][1]=f[i1][j1][1]+f[i1][j][1]+f[i1][j1][0]2


    关于i-1,i不相邻,也就是f[i][j][0]怎么推
    本来i-1与i-2相邻,将i插入j对相邻的数的任意一对,这样就破坏了一对,这样方案来源于f[i-1][j+1][1],有(j+1-1)种位置可以选(i-1与i-2那对不能拆,因为插入又会形成新的)。
    本来i-1与i-2不相邻,将i插入j对相邻的数的任意一对,这样就破坏了一对,这样方案来源于f[i-1][j+1][0],有(j+1)种位置可以选。
    又可能i不去拆开相邻的数,就可以来源于
    f[i-1][j][1]*(i-j-1)(可以插入i-1与i-2,不改变对数) 或 f[i-1][j][0]*(i-j-2)
    综合

    f[i][j][0]=f[i1][j+1][1]j+f[i1][j+1][0](j+1)+f[i1][j][1](ij1)+f[i1][j][0](ij2)

    很难推的题呀。。。。

    题干:

    Description
    n 个沙茶,被编号 1~n。排完队之后,每个沙茶希望,自己的相邻的两
    人只要无一个人的编号和自己的编号相差为 1(+1 或-1)就行; 
    现在想知道,存在多少方案满足沙茶们如此不苛刻的条件。 
    
    Input
    只有一行且为用空格隔开的一个正整数 N,其中 100%的数据满足 1≤N ≤ 1000; 
    
    Output
    一个非负整数,表示方案数对 7777777 取模。   
    
    Sample Input
    4               
    Sample Output
    2 
    
    样例解释:有两种方案 2 4 1 33 1 4 2 
    HINT
    
    Source

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define duke(i,a,n) for(int i = a;i <= n;i++)
    #define lv(i,a,n) for(int i = a;i >= n;i--)
    #define clean(a) memset(a,0,sizeof(a))
    const int INF = 1 << 30;
    const int mod = 7777777;
    typedef long long ll;
    typedef double db;
    template <class T>
    void read(T &x)
    {
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x)
    {
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    ll dp[1010][1010][3];
    int main()
    {
        int n;
        read(n);
        dp[1][0][0] = 1;
        duke(i,2,n)
        {
            duke(j,0,i)
            {
                dp[i][j][1] = (dp[i - 1][j - 1][1] + dp[i - 1][j][1] + dp[i - 1][j - 1][0] * 2) % mod;
                dp[i][j][0] = (dp[i - 1][j][0] * (i - j - 2) + dp[i - 1][j + 1][1] * j + dp[i - 1][j + 1][0] * (j + 1) + dp[i - 1][j][1] * (i - j - 1)) % mod;
            }
        }
        printf("%lld
    ",dp[n][0][0]);
        return 0;
    }
  • 相关阅读:
    8.6 First_value和Last_value
    iOS_第3方类库_側滑选项卡SlideSwitchView
    公开的函数把函数作为參数
    .NET 框架简单介绍
    HDU-3577-Fast Arrangement-区间更新
    拥抱PBO(基于项目的组织)聚焦核心价值创造
    一个使用sbt编译的JNI C++ 的模板
    BestCoder Round #1
    饭统网倒闭:不创新、不放权就是作死 .
    【SSH 基础】浅谈Hibernate关系映射(3)
  • 原文地址:https://www.cnblogs.com/DukeLv/p/9535798.html
Copyright © 2011-2022 走看看