遞推 vijos1060 盒子

2021-07-16 05:41:03 字數 3418 閱讀 8613

p1060盒子

accepted

描述n個盒子排成一行(1<=n<=20)。你有a個紅球和b個藍球。0 <= a <= 15, 0 <= b <= 15。球除了顏色沒有任何區別。你可以將球放進盒子。乙個盒子可以同時放進兩種球,也可以只放一種,也可以空著。球不必全部放入盒子中。程式設計計算有多少種放置球的方法。

格式 輸入格式

一行,n,a,b,用空格分開。

輸出格式

一行,輸出放置方案總數。

樣例1

樣例輸入1

2 1 1
樣例輸出1

9
限制

1s方案數,又是方案數!

題目大意:給你n個排成一排的盒子,每個盒子裡面可以不放入,單放入一些紅球或者放入一些藍球,同時放入兩種球(都是若干個,注意原題說的是放入兩種球不是最多只能放兩個球哦)。然後要求的是滿足最後用的紅球不超過a個,藍球不超過b個的方案數。

演算法一:根據原題所說,用回溯暴力的模擬裝球的過程,每考慮完所有的盒子方案數就疊加1。時間複雜度不穩定 最壞是o((ab)^n) 預期得分25~30

演算法一**如下:

#include

#include

#include

#include

#include

using

namespace

std;

typedef

unsigned

long

long ll;

const

int maxn=25;

int n,a,b;

bool vis[maxn][maxn][maxn];

ll ans=0;

void run(int i,int j,int k)

//當前考慮第i個盒子的放置情況,此時已經放了j個紅球,k個藍球。

for(int a=0;a<=a-j;a++)

for(int b=0;b<=b-k;b++)//if(!vis[i][a][b])

}int main()

演算法二:方案問題,我們很容易想到遞推,根據本題的要求和」求什麼就設什麼」的原則比較容易想到狀態函式f(i,j,k)表示用不超過j個紅球,不超過k個藍球放前i個盒子的方案數。

分析第i個盒子的選擇,顯然第i個盒子可以不放球 或者 單放乙個紅球 或者 單放兩個紅球 … 或者 單放i個紅球 或者 單放乙個藍球 或者 單放兩個藍球 … 或者 單放j個藍球 或者 放乙個紅球乙個藍球 …

根據狀態轉移的思想 寫出遞推方程:

f(i,j,k)=f(i-1,j,k)+f(i-1,j,k-1)+…+f(i-1,j,0)

+f(i-1,j-1,k)+f(i-1,j-1,k-1)+…+f(i-1,j-1,0)

+… +f(i-1,0,k)+f(i-1,0,k-1)+…+f(i-1,0,0)

即f(i,j,k)+=f(i-1,x,y)| 0<=x<=j 0<=y<=k

邊界是f(0,j,k)=1

時間複雜度o(a^2*b^2*n) 預期得分100

演算法二的**實現:

#include

#include

#include

#include

#include

using namespace std;

typedef unsigned long long ll;

const int maxn=25;

int n,a,b;

ll f[maxn][maxn][maxn];

/* f(i,j,k)=在前i個盒子裡面放不多於j個紅球,不多於k個籃球的方案數.

f(i,j,k)=f(i-1,j,k)+f(i-1,j-1,k)+...+f(i-1,j,k-1)+...+f(i-1,j-1,k-1)+...

f(0,i,j)=1;

*/int main()

演算法三:優化遞推

由於a,b兩球除了顏色之外其餘的屬性都相同,不如將兩種球分別處理。

此時設f(i,j)表示選不超過j個球放入前i個盒子。

假設只有a球 f(n,a)就是n個盒子,a個紅球的方案數。

假設只有b球 f(n,b)就是n個盒子,b個紅球的方案數。

由乘法原理,最後的答案是f(n,a)*f(n,b)

同樣分析第i個盒子的情況,可以不選球,可以選乙個,可以選兩個…

對應的遞推方程:f(i,j)=f(i-1,j)+f(i-1,j-1)+f(i-1,j-2)+…+f(i-1,0)=sigma(f(i-1,x)) | 0<=x<=j

邊界分析 f(0,j)=1

這種方法的時間複雜度o(n*max(a,b)^2)

實現遞推的**:

for(int j=0; j

<=a || j

<=b ;j++)

f[0]

[j]=1;

for(int i=1;i

<=n;i++)

for(int j=0; j

<=a || j

<=b ;j++)

for(int k=0;k<=j;k++)

觀察到填表實現時f[i][j]的值其實是上一行所有f[i-1][j]的和,還可以繼續用字首和的思想優化,在列舉j的時候就算出t,然後再改變f[i][j]的值。

完整**:

#include

#include

#include

#include

#include

using

namespace

std;

typedef

unsigned

long

long ll;

const

int maxn=25;

int n,a,b;

ll f[maxn][maxn];

/* f(i,j)=在前i個盒子裡面放不多於j個球的方案數

f(i,j)=f(i-1,j)+f(i-1,j-1)+...+f(i-1,0);

ans=f(n,a)*f(n*b);

f(0,j)=1; | 0<=j<=max(a,b)

*/int main()

}cout

<'\n';

return

0;}

考試的總結:考的時候,只想到了第二種方法,資料也小,確實也能過。今天聽評講,mr.he提了乙個問題,如果n能到1000,a,b都能到500,對方案要取模怎麼辦。聯想的考的第二個題,這樣搞絕對要爆記憶體(128m),結果mr.he講了這個第三種優化方法,直接開二維就行了,時間也比三維的快,雖然寫了搜尋對拍過了,我覺得我還是沒做到一題多解,看來還是要多想啊!

習題3 10 盒子

這道題目簡單的判斷很容易對特殊情況的忽略,這裡自己想了一下與其他人不一樣的角度來做的,若是被來客看到的話,還望指點指點 給定6個矩形的長和寬wi和hi 1 wi,hi 1000,都為整數 判斷它們能否構成長方體的6個面。若能構成,就輸出possible,不能,輸出impossible。樣例輸入 13...

CSS學習 2 盒子

css2.1還包含outline屬性。與border屬性不同,輪廓繪製在元素框之上,所以它們不影響元素的大小或定位。因此輪廓有助於修復bug,因為它們不影響頁面的布局。大多數現代瀏覽器 包括ie8 支援輪廓,但是ie7和更低版本不支援輪廓。內邊距 邊框和外邊距都是可選的,預設值為零。但是,許多元素將...

NYOJ 562 盒子遊戲

時間限制 1000 ms 記憶體限制 65535 kb 難度 3 描述 有兩個相同的盒子,其中乙個裝了 n 個球,另乙個裝了乙個球。alice 和 bob 發明了乙個遊戲,規則如下 alice 和 bob 輪流操作,alice 先操作。每次操作時,遊戲者先看看哪個盒子裡的球的數目比較少,然後清空這個...