AcWing 271. 杨老师的照相排列

AcWing 271. 杨老师的照相排列_第1张图片
输入样例

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/

AcWing 271. 杨老师的照相排列_第2张图片
yxc老师yyds
讲的真很细
首先分几种情况:把每一排的最后一个数(最大的数插进去的点)类似于去除,然后加上这一形状的方案数,(就是这一形状的方案数),然后向前递归(直接从小到大就实现了),我自己脑子演示了一遍,这方法很好,但是我也有注意到要是上下两行相等的话不能去除,看到老师的代码,我就知道用if就可以解决问题。也学到了一个新的指针,干货很多呀

#include
#include
#include
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;
    }
}

在这里插入图片描述
然后数据多而且大,时间看起来像超时的样子。

你可能感兴趣的:(线性dp,算法,c++)