AcWing 271. 楊老師的照相排列

在這裏插入圖片描述
輸入樣例

1
30
5
1 1 1 1 1
3
3 2 1
4
5 3 3 1
5
6 5 4 3 2
2
15 15
0

輸出樣例

1
1
16
4158
141892608
9694845

這道題相對來說,我第一次感受到了壓力吧,這道題我也看出來要是dfs一定百分百超時,要用dp做,用dp又不知道思路,無敵的yxc老師來了!!!!

https://www.acwing.com/video/397/

在這裏插入圖片描述
yxc老師yyds
講的真很細
首先分幾種情況:把每一排的最後一個數(最大的數插進去的點)類似於去除,然後加上這一形狀的方案數,(就是這一形狀的方案數),然後向前遞歸(直接從小到大就實現了),我自己腦子演示了一遍,這方法很好,但是我也有注意到要是上下兩行相等的話不能去除,看到老師的代碼,我就知道用if就可以解決問題。也學到了一個新的指針,乾貨很多呀


#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=31;
LL f[N][N][N][N][N];
int s[6];
int main(void)
{
   
   
    int n;
    while(cin>>n,n)
    {
   
   
        memset(s,0,sizeof(s));
        for(int i=1;i<=n;i++)  cin>>s[i];
        memset(f,0,sizeof(f));
        f[0][0][0][0][0]=1;//因爲求的是方案,要以此往後遞推
        for(int a=0;a<=s[1];a++)
        for(int b=0;b<=s[2];b++)
        for(int c=0;c<=s[3];c++)
        for(int d=0;d<=s[4];d++)
        for(int e=0;e<=s[5];e++)
        {
   
   
            LL &v=f[a][b][c][d][e];//用指針操作減少了寫代碼的麻煩
           //每一行都要判斷是否爲0,並且是否減去這個還滿足這個結構
            if(a&&a-1>=b) v+=f[a-1][b][c][d][e];
            if(b&&b-1>=c) v+=f[a][b-1][c][d][e];
            if(c&&c-1>=d) v+=f[a][b][c-1][d][e];
            if(d&&d-1>=e) v+=f[a][b][c][d-1][e];
            if(e) v+=f[a][b][c][d][e-1];
        } 
        cout<<f[s[1]][s[2]][s[3]][s[4]][s[5]]<<endl;
    }
}

在這裏插入圖片描述
然後數據多而且大,時間看起來像超時的樣子。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章