• [AHOI2009]中国象棋


    旁边的dalao们,神们,都在做什么树套树平衡树LCT仙人掌模拟退火AC自动机……只有笔者这个蒟蒻弱弱的在写DP。这道Dp还是很有技术含量的。。

    先分析一下题目,简单来说就是给一个矩阵,要求再里面放棋子,每行每列的棋子要<=2,问有多少种不同的放置方法。首先分析小数据,n,m均<=6,爆搜即可出解。然后那50%估计是有什么nm^3的做法,然而笔者太弱了没想出来。那么接着分析100%。

    考虑到这个题就给了你行和列,所以我们以 行 为大方向考虑动归方程。思考,这么一来我们每行最多只能放两个棋子,那么如果我们以f[i][j][k]来表示到第i行已经有j列放了一个棋子,k列放了两个棋子的方法数量,那么DP完成后我们的答案就是sum(f[n][1...m][1...m])。考虑如何转移:

      首先,我们在下一行不放棋子,那么直接转移这一行的方案数就可以了。

      其次,我们考虑在下一行放一个棋子,那么必须要分情况讨论:

      ①我们在当前已经有一个棋子的一列在放一个棋子,那么状态变为f[i+1][j-1][k+1],而我们可以这么做的方案数就是已经放了j列一个棋子的j。

      ②我们从找一列一个棋子都没有的,放一个棋子,那么状态变为f[i+1][j+1][k],我们能这么做的次数就是当前没有放旗子的列数(m-j-k)。

      最后我们考虑在下一行放两个棋子,仍然需要分情况讨论,

      ①我们把这两个棋子全都放到已经有棋子的列,那么状态变为f[i+1][j-2][k+2],我们可行的不同的方案数就是从j个里面选出两个的数量也就是Cj2

      ②我们放一个棋子在已经有棋子的一列,而另一个放在没有棋子的一列,那么状态变为f[i+1][j][k+1],可行的不同方案数的个数是可以放有一个棋子的j和一个棋子都没有的(m-j-k)的乘积。

      ③我们把两个棋子都放在原来没有棋子的列上,那么状态变为f[i+1][j+2][k],我们可行的方案数是。。

    适当的%有益于身心,代码确实不长,但是确实是一道DP好题。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<algorithm>
     6 #include<queue>
     7 #define inf 5000001
     8 #define re register
     9 #define ll long long
    10 #define min(a,b) a<b?a:b 
    11 #define maxn 5000007
    12 #define mo 9999973
    13 using namespace std;
    14 ll f[201][201][201],n,k,m;
    15 inline ll C(int x)
    16 {
    17     return x*(x-1)/2;
    18 }
    19 int main()
    20 {
    21     cin>>n>>m;
    22     f[0][0][0]=1;
    23     for(re int i=0;i<n;i++)
    24      for(re int j=0;j<=m;j++)
    25       for(re int l=0;l+j<=m;l++){
    26           if(f[i][j][k]){
    27               f[i+1][j][l]=(f[i+1][j][l]+f[i][j][l])%mo;
    28               
    29             if(m-j-l>=1) f[i+1][j+1][l]=(f[i+1][j+1][l]+f[i][j][l]*(m-j-l))%mo;
    30               if(j>=1) f[i+1][j-1][l+1]=(f[i+1][j-1][l+1]+f[i][j][l]*(j))%mo;
    31               
    32             if(m-j-l>=2) f[i+1][j+2][l]=(f[i+1][j+2][l]+f[i][j][l]*C(m-j-l))%mo;
    33               if(m-j-l>=1&&j>=1) f[i+1][j][l+1]=(f[i+1][j][l+1]+f[i][j][l]*(m-j-l)*j)%mo;
    34               if(j>=2) f[i+1][j-2][l+2]=(f[i+1][j-2][l+2]+f[i][j][l]*C(j))%mo;
    35           
    36           }
    37       }
    38     ll ans=0;
    39     for(re int i=0;i<=m;i++)
    40      for(re int j=0;j<=m;j++)
    41      ans=(ans+f[n][i][j])%mo;
    42     cout<<ans;
    43 }
  • 相关阅读:
    转载 | python inferface使用
    gasshopper之python电池输出dict结构
    Tensorflow 2.0 搭建神经网络(局部)
    grasshopper之python电池执行逻辑
    springboot中给属性文件内容加密(application.properties,application.yml)
    使用docker安装rabbitmq
    关于宝塔Linux面板
    winsw来设置window自启服务
    docker的使用,Nginx,Tomcat,Portainer可视化
    内网穿透(windows)
  • 原文地址:https://www.cnblogs.com/victorique/p/8619223.html
Copyright © 2020-2023  润新知