zoukankan      html  css  js  c++  java
  • [BZOJ 1801] Chess

    Link:

    BZOJ 1801 传送门

    Solution:

    一眼看过去又像是状压$dp$的经典模型……

    但此题$n,mle 100$ ,直接跑状压只有50分

    此时要发现这道题的特点:每行/列不能放置超过2个

    既然每一列只可能有 不选/选1个/选2个 这三种状态,直接记录这三种状态的个数即可

    于是设$dp[i][j][k]$为到第$i$行时,有$j$列放置了1个,有$k$列放置了2个的方案数

    接下来分五种情况递推就行了

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const int MAXN=105,MOD=9999973;
    int n,m,cur;
    ll dp[2][MAXN][MAXN],res;
    
    ll C(int a)
    {return 1ll*a*(a-1)/2;}
    
    int main()
    {
        scanf("%d%d",&n,&m);
        
        dp[cur^1][0][0]=1;
        for(int i=1;i<=n;i++,cur^=1)
            for(int j=0;j<=m;j++) for(int k=0;j+k<=m;k++)
            {
                dp[cur][j][k]=dp[cur^1][j][k];
                if(k>=1) (dp[cur][j][k]+=dp[cur^1][j+1][k-1]*(j+1))%=MOD;
                if(j>=1) (dp[cur][j][k]+=dp[cur^1][j-1][k]*(m-j-k+1))%=MOD;
                if(j>=2) (dp[cur][j][k]+=dp[cur^1][j-2][k]*C(m-j-k+2))%=MOD;
                if(k>=2) (dp[cur][j][k]+=dp[cur^1][j+2][k-2]*C(j+2))%=MOD;
                if(k>=1) (dp[cur][j][k]+=dp[cur^1][j][k-1]*j*(m-j-k+1))%=MOD;
            }
        for(int i=0;i<=m;i++) for(int j=0;i+j<=m;j++)
            (res+=dp[cur^1][i][j])%=MOD;
        printf("%lld",res);
        return 0;
    }

    Reviews:

    感觉现在想问题还是太定式了

    更重要的是找到每道题的特点

    对于总状态数较少的题目直接记录每种状态的个数$dp$即可,仅当状态数过多状压

  • 相关阅读:
    TLE: poj 1011 Sticks
    UVa 116 Unidirectional TSP
    csuoj 1215 稳定排序
    UVa 103 Stacking Boxes
    UVa 147 Dollars
    UVa 111 History Grading
    怎么在ASP.NET 2.0中使用Membership
    asp.net中如何删除cookie?
    ASP.NET中的HTTP模块和处理程序[收藏]
    NET开发中的一些小技巧
  • 原文地址:https://www.cnblogs.com/newera/p/9256810.html
Copyright © 2011-2022 走看看