POJ - 2279 Mr. Young‘s Picture Permutations

题意:

输入每一排的人数,保证前一排的人数大于后一排,要求每一排从左到右编号递增,每一列从前往后编号递增,输出方案数。最多5排,最多30个编号。

题解:

显然可以使用动态规划。用 f [ i 1 ] [ i 2 ] [ i 3 ] [ i 4 ] [ i 5 ] f[i_1][i_2][i_3][i_4][i_5] f[i1][i2][i3][i4][i5]表示第1排有 i 1 i_1 i1个人,第2排有 i 2 i_2 i2个人,第3排有 i 3 i_3 i3个人,第4排有 i 4 i_4 i4个人,第5排有 i 5 i_5 i5个人时的方案数。如果没有那么多排,直接当成这一排最多有0人即可。

动态规划的精髓就是转移方程,我们经常想的是当前状态可以从哪些状态转移而来,其实也可以考虑当前状态可以转移到哪些状态。对于 f [ i 1 ] [ i 2 ] [ i 3 ] [ i 4 ] [ i 5 ] f[i_1][i_2][i_3][i_4][i_5] f[i1][i2][i3][i4][i5],如果新增一个人,那么

  • 这一排的人数还没有满
  • 如果不插在第1排,那么就要求这一排的人数小于前一排。否则之后一定在前面一排插入人,就会导致前排的人的序号大于后排的。

AC代码:

#include <cstdio>
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <iomanip>
#include <cstdlib>
#define pb push_back 
#define fir first
#define sec second
#define All(x) x.begin(),x.end() 
#define ms(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define lep(i,a,b) for(int i=(a);i>=(b);i--) 
#define INF 0x3f3f3f3f
#define multi int T;scanf("%d",&T);while(T--) 
using namespace std;
typedef long long ll;
typedef double db;
const int N=35;
const int mod=10007;
const db pi=acos(-1.0);
int a[7],n;
ll f[N][N][N][N][N];
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("D:\\work\\data.in","r",stdin);
    #endif
    int k,sum=0;
    while(scanf("%d",&k),k){
        for(int i=1;i<=k;i++) scanf("%d",&a[i]);
        for(int i=k+1;i<=5;i++) a[i]=0;
        rep(i1,0,a[1])
            rep(i2,0,a[2])
                rep(i3,0,a[3])
                    rep(i4,0,a[4])
                        rep(i5,0,a[5]) f[i1][i2][i3][i4][i5]=0;
        f[0][0][0][0][0]=1;
        rep(i5,0,a[5])
            rep(i4,0,a[4])
                rep(i3,0,a[3])
                    rep(i2,0,a[2])
                        rep(i1,0,a[1]){
                            if(i5<a[5]&&i5<i4)
                                f[i1][i2][i3][i4][i5+1]+=f[i1][i2][i3][i4][i5];
                            if(i4<a[4]&&i4<i3)
                                f[i1][i2][i3][i4+1][i5]+=f[i1][i2][i3][i4][i5];
                            if(i3<a[3]&&i3<i2)
                                f[i1][i2][i3+1][i4][i5]+=f[i1][i2][i3][i4][i5];
                            if(i2<a[2]&&i2<i1)
                                f[i1][i2+1][i3][i4][i5]+=f[i1][i2][i3][i4][i5];
                            if(i1<a[1])
                                f[i1+1][i2][i3][i4][i5]+=f[i1][i2][i3][i4][i5];
                        }
        printf("%lld\n",f[a[1]][a[2]][a[3]][a[4]][a[5]]);
    }
        
}

猜你喜欢

转载自blog.csdn.net/Luowaterbi/article/details/109086958