日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

AHOI2009 中国象棋

發布時間:2025/7/14 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AHOI2009 中国象棋 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接

題目描述

在一個N行M列的棋盤上,讓你放若干個炮(可以是0個),使得沒有一個炮可以攻擊到另一個炮,請問有多少種放置方法。
(在中國象棋中炮的行走方式是:一個炮攻擊到另一個炮,當且僅當它們在同一行或同一列中,且它們之間恰好 有一個棋子。)

輸入輸出格式

輸入格式:

一行包含兩個整數N,M,之間由一個空格隔開。

輸出格式:

總共的方案數,由于該值可能很大,只需給出方案數模9999973的結果。

樣例

輸入樣例輸出樣例
1 37

思路

1. 30分做法

dfs,復雜度玄學

沒有代碼

2.50分做法

分析題目
當滿足題意下,每行每列有且最多只有兩個炮
注意題目保證行或列小于等于8
考慮dp 按行或列轉移(假設按行轉移,即n<=8)
如果知道了考慮到當前行時,每列已經放了的棋子個數
那么當前行放棋子的方案就能夠確定(每行最多放兩個)
那么如果會狀壓的同學應該已經會了 (逃
定義dp[n][4^m]表示當考慮到第n行時,之前所放的棋子狀態為2^2m時的方案數
通過兩位二進制表示一列的狀態 00代表沒有放棋子 01代表放了一個棋子 11代表不能再放棋子
然后轉移就可以了

沒有代碼

3.滿分做法

考慮dp轉移過程

  • 不選
  • 選00->01
  • 選01->11
  • 選00,00->01,01
  • 選00,01->01,11
  • 選01,01->11,11

如果你發現,轉移并不用知道每一列究竟放了幾個棋子的話...
定義dp[n][i][j]表示當考慮到第n行時,沒有放棋子的有i列,放了一個棋子的有j列

定義C(x,y)為在x中取y個的方案數
那么上面的轉移過程表示出來就是

  • C(i+j,0)
  • C(i,1)
  • C(j,1)
  • C(i,2)
  • C(i,1)*C(j,1)
  • C(j,2)

假設現在取了 00,01
那么就有 dp[n+1][i-1][j-1]=dp[n][i][j]*C(i,1)*C(j,1)

有代碼
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define rint register int #define ci const int& #define ll long long using namespace std;const int mod=9999973; ll dp[101][102][102]; int n,m; ll ans=0;int main(){cin>>n>>m;//初始化,在第0行,放了1個的列為0(即01為0),放了0個的列為m(即00為m)的情況數有一種 dp[0][0][m]=1;for(rint i=0;i<n;i++)for(rint j=0;j<=m;j++)for(rint k=0;k<=m-j;k++)if(dp[i][j][k]){//如果狀態可到達 if(k){//當00數>=1時 if(j)dp[i+1][j][k-1]+=dp[i][j][k]*k*j,dp[i+1][j][k-1]%=mod;//當01數>=1時,選00,01放置 dp[i+1][j+1][k-1]+=dp[i][j][k]*k;dp[i+1][j+1][k-1]%=mod;//選00放置 if(k>1)dp[i+1][j+2][k-2]+=dp[i][j][k]*k*(k-1)/2,dp[i+1][j+2][k-2]%=mod;//當00數>=2時,選00,00放置 }if(j){//當01數>=1時 dp[i+1][j-1][k]+=dp[i][j][k]*j;dp[i+1][j-1][k]%=mod;//選01放置 if(j>1)dp[i+1][j-2][k]+=dp[i][j][k]*j*(j-1)/2,dp[i+1][j-2][k]%=mod;//當01數>=2時,選01,01放置 }dp[i+1][j][k]+=dp[i][j][k];dp[i+1][j][k]%=mod;//不放 }for(rint j=0;j<=m;j++)for(rint k=0;k<=m-j;k++)if(dp[n][j][k])(ans+=dp[n][j][k])%=mod;//統計 cout<<ans;//dp數組用long long,中間存在乘法,極限情況下會爆int,親身試驗.... }

轉載于:https://www.cnblogs.com/ullio/p/9369323.html

總結

以上是生活随笔為你收集整理的AHOI2009 中国象棋的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。