【UVA1638】杆子的排列
生活随笔
收集整理的這篇文章主要介紹了
【UVA1638】杆子的排列
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題面
有高為 1, 2, …, n 的 n 根桿子排成一排, 從左向右能看到 L 根, 從右向左能看到 R 根。求有多少種可能的排列方式。
分析
數據范圍僅200,本來是往組合數學方面想的,看到了這個200就放棄了念頭,果然是dp
定義dp[i][j][k]是用了高度為1~i的桿子,從左邊能看到j個,從右邊能看到k個
如果從1轉移到n很困難,因為放一個高的桿子進去會造成很多的遮擋影響,是幾乎不能維護的。于是考慮從n轉移到1,即先放比較高的桿子
加上放好了2~n高度的桿子,再放高度為1的桿子僅有三種情況
1.放在最左邊。僅僅是從左看能多看到一個 dp[i][j][k]+=dp[i-1][j-1][k]
2.放在最右邊,同理
3.放在中間,一定會被擋住。i-1根桿子間有(i-2)個可以放置的空格,則dp[i][j][k]+=dp[i-1][j][k]*(i-2)。
其實這里i的定義已經發生了一點變化,但是狀態轉移是很容易理解的
為什么可以把i等效定義為i個,而不是1~i呢?其實這只需要代表是i根高度不同的桿子,2~i的桿子全部砍1,相對高度沒有變,也就等效成了1~i-1的桿子
代碼
#include<bits/stdc++.h> using namespace std; #define mod 998244353 #define ll long long #define N 220 ll dp[N][N][N]; ll t,n,l,r; int main() { dp[1][1][1]=1;for(ll i=2;i<=200;i++)for(ll j=1;j<=i;j++)for(ll k=1;k<=i-j+1;k++)dp[i][j][k]=(dp[i-1][j-1][k]+dp[i-1][j][k-1]+dp[i-1][j][k]*(i-2)%mod)%mod;scanf("%lld",&t); while(t--){scanf("%lld%lld%lld",&n,&l,&r);printf("%lld\n",dp[n][l][r]);} return 0; }?
轉載于:https://www.cnblogs.com/NSD-email0820/p/9561589.html
總結
以上是生活随笔為你收集整理的【UVA1638】杆子的排列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java -TCP通信
- 下一篇: react-native scrollv