• 《算法竞赛进阶指南》0x51线性DP 照相馆排列


    题目链接:https://www.acwing.com/problem/content/273/

    题目要求将N个人排成不超过五列,每列的人数限制而且递减,现在要求每行每列都是递减的方案的数量,通过状态集合以及转移规律,f[a][b][c][d][e]满足索引递减的性质 ,在转移的时候要维护这个性质,所以除了e以为的所有的索引-1情况都需要考虑,e-1的情况自然维护了这个性质。此外,从高到低排这些人,当前要排的人排在哪一行就是决策的划分过程,当前决策中的方案数量等价于之前阶段的某一个决策的方案数,所以直接累加转移的方案即可。

    在DP问题中,集合和集合划分的概念十分重要,本问题中的集合上的属性是数量。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<string.h>
    using namespace std;
    const int maxn = 31;
    typedef long long ll;
    ll f[maxn][maxn][maxn][maxn][maxn];
    int n;
    int main(){
        while(scanf("%d",&n) && n){
            int s[5]={0};
            for(int i=0;i<n;i++)cin>>s[i];
            memset(f,0,sizeof(f));
            f[0][0][0][0][0]=1;
            for(int a=0;a<=s[0];a++)//保证后一排填的人比前面的小 
                for(int b=0;b<=min(s[1],a);b++)
                    for(int c=0;c<=min(s[2],b);c++)
                        for(int d=0;d<=min(c,s[3]);d++)
                            for(int e=0;e<=min(s[4],d);e++)
                            {// f[a][b][c][d][e]满足索引递减的性质 
                                ll& v=f[a][b][c][d][e];
                                if(a && a>b)v+=f[a-1][b][c][d][e];
                                if(b && b>c)v+=f[a][b-1][c][d][e];
                                if(c && c>d)v+=f[a][b][c-1][d][e];
                                if(d && d>e)v+=f[a][b][c][d-1][e];
                                if(e)v+=f[a][b][c][d][e-1];
                            }
            
            printf("%lld
    ",f[s[0]][s[1]][s[2]][s[3]][s[4]]);
        }
    } 
    每一个不曾起舞的日子,都是对生命的辜负。
  • 相关阅读:
    让程序在后台长久运行的方法
    unrecognized selector sent to instance的定位
    CocoaLumberjack调试的简单使用
    #pragma
    __bridge __bridge_retained __bridge_transfer
    关于c#继承
    C#__ 模拟鼠标单击事件
    C# 调用win api获取chrome浏览器中地址
    认识安卓
    源码解析-Volley(转自codeKK)
  • 原文地址:https://www.cnblogs.com/randy-lo/p/13377523.html
Copyright © 2020-2023  润新知