Mr. Young's Picture Permutations
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 5841   Accepted: 1860

Description

Mr. Young wishes to take a picture of his class. The students will stand in rows with each row no longer than the row behind it and the left ends of the rows aligned. For instance, 12 students could be arranged in rows (from back to front) of 5, 3, 3 and 1 students.

X X X X X

X X X

X X X

X

In addition, Mr. Young wants the students in each row arranged so
that heights decrease from left to right. Also, student heights should
decrease from the back to the front. Thinking about it, Mr. Young sees
that for the 12-student example, there are at least two ways to arrange
the students (with 1 as the tallest etc.):

 1  2  3  4  5     1  5  8 11 12

6 7 8 2 6 9

9 10 11 3 7 10

12 4

Mr. Young wonders how many different arrangements of the students
there might be for a given arrangement of rows. He tries counting by
hand starting with rows of 3, 2 and 1 and counts 16 arrangements:

123 123 124 124 125 125 126 126 134 134 135 135 136 136 145 146

45 46 35 36 34 36 34 35 25 26 24 26 24 25 26 25

6 5 6 5 6 4 5 4 6 5 6 4 5 4 3 3

Mr. Young sees that counting by hand is not going to be very
effective for any reasonable number of students so he asks you to help
out by writing a computer program to determine the number of different
arrangements of students for a given set of rows.

Input

The
input for each problem instance will consist of two lines. The first
line gives the number of rows, k, as a decimal integer. The second line
contains the lengths of the rows from back to front (n1, n2,..., nk) as
decimal integers separated by a single space. The problem set ends with a
line with a row count of 0. There will never be more than 5 rows and
the total number of students, N, (sum of the row lengths) will be at
most 30.

Output

The
output for each problem instance shall be the number of arrangements of
the N students into the given rows so that the heights decrease along
each row from left to right and along each column from back to front as a
decimal integer. (Assume all heights are distinct.) The result of each
problem instance should be on a separate line. The input data will be
chosen so that the result will always fit in an unsigned 32 bit integer.

Sample Input

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

Sample Output

1
1
16
4158
141892608
9694845

题目不难,有几个值得学习的地方(就是我不会的地方)
首先是这个思考方式,也就是对这个问题特征的分析
我们要计算所有的方式,计数类题目基本都是这种套路,要么是直接用数学大力分析一手,然后各种组合数乘法原理加法原理
要么就是根据这个题目的特别性进行一个稍微类似枚举的过程
对于这个,直接枚举所以可能性自然是非常的不可行的,连样例都不可能过
我们考虑一个构造的过程,假设我们已经有了一个不完整但是暂时合法的组合,我们考虑给它加上一个数字
可以发现,如果这个是合法的,那么它从左上到右下的数字应该是在逐渐增大的(并不严谨,但是可以先这样理解一下)
那么我们就从左上方开始构造,因为可以发现1永远要在左上角,这个应该是容易证明的
我们就从这个确定的1开始,保证这个方阵合法的情况下,向着左边和下边进行构造
我们试着把所有数字从1开始由小到大逐渐放进这个方阵中,为了保证这个方阵始终合法,我们需要考虑一下应该按照什么样子的规则来进行
首先,每一个数字下面的的数字肯定是要比这个数字大的,而我们在构造的时候是从小到大的,所以只要后放就更大
也就是说,一个数字右边或者是下面的数字肯定是要在这个数字后放的。
也就是说,在一个数字被放下前,它的上面和左边的数字肯定是已经被放好的。

利用这个规则,我们就可以开始dp了
设f[a][b][c][d][e]为当第一排有a个人,第二排有b个人,第三排有c个人·····时的合法方案数
用k[i]表示第i排最多的人数
转移(也许算是递推吧?)的方程就是

对于第一排,当a<k1时,让f[a+1][b][c][d][e]+=f[a][b][c][d][e]
对于下面的则是,当b<k2且b<a,让f[a][b+1][c][d][e]+=f[a][b][c][d][e]
剩下的也是以此类推

附上代码
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <math.h>
#include <string.h>
#define ll long long
using namespace std;
inline int read() {
char c=getchar();int a=0,b=1;
for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
for(;c>='0'&&c<='9';c=getchar())a=a*10+c-48;return a*b;
}
int k[6],n,tot;
int main()
{
while(n=read())
{
if(n==0)break;
tot=0;
memset(k,0,sizeof(k));
for(int i=1;i<=n;i++)
k[i]=read(),tot+=k[i];
unsigned ll f[k[1]+1][k[2]+1][k[3]+1][k[4]+1][k[5]+1];
memset(f,0,sizeof(f));
f[0][0][0][0][0]=1;
for(int k1=0;k1<=k[1];k1++)
{
for(int k2=0;k2<=k[2];k2++)
{
for(int k3=0;k3<=k[3];k3++)
{
for(int k4=0;k4<=k[4];k4++)
{
for(int k5=0;k5<=k[5];k5++)
{
if(k1<k[1])f[k1+1][k2][k3][k4][k5]+=f[k1][k2][k3][k4][k5];
if(k2<k1&&k2<k[2])f[k1][k2+1][k3][k4][k5]+=f[k1][k2][k3][k4][k5];
if(k3<k2&&k3<k[3])f[k1][k2][k3+1][k4][k5]+=f[k1][k2][k3][k4][k5];
if(k4<k3&&k4<k[4])f[k1][k2][k3][k4+1][k5]+=f[k1][k2][k3][k4][k5];
if(k5<k4&&k5<k[5])f[k1][k2][k3][k4][k5+1]+=f[k1][k2][k3][k4][k5];
}
}
}
}
}//我在干什么?
cout<<f[k[1]][k[2]][k[3]][k[4]][k[5]]<<endl;
}
return 0;
}

这个空间真的是。。。

魔幻

这题主要是这个计数,我之前好像总结过?有点印象,但是已经过去太久了,忘记了。
一个主要的点就是,对于每一道题目,都要分析一下题目的特征或者说是特性,这是解题的关键,也是题目的难点(一般来说)
而这种加法来计数的,也就是这一类构造题目的一个解题方向
也是应该从中积累和学习到的东西

 

poj2279的更多相关文章

  1. POJ2279 Mr Young's Picture Permutations

    POJ2279 Mr Young's Picture Permutations 描述: 有N个学生合影,站成左对齐的k排,每行分别有N1,N2…NK个人,第一排站最后,第k排站之前.学生身高依次是1… ...

  2. 【题解】POJ2279 Mr.Young′s Picture Permutations dp

    [题解]POJ2279 Mr.Young′s Picture Permutations dp 钦定从小往大放,然后直接dp. \(dp(t1,t2,t3,t4,t5)\)代表每一行多少人,判断边界就能 ...

  3. poj2279——Mr. Young's Picture Permutations

    Description Mr. Young wishes to take a picture of his class. The students will stand in rows with ea ...

  4. poj2279 线性dp

    #include<iostream> #include<cstdio> #include<cstring> #define ll long long using n ...

  5. POJ2279杨氏矩阵+钩子定理

    题目:http://poj.org/problem?id=2279 有dp做法,但会MLE. dp的思想很好,是通过 “按身高由小到大往进放” 把 “身高小于” 的条件转化成 “放进去的先后” ,于是 ...

  6. poj2279排队——杨氏矩阵与钩子公式(DP爆内存)

    题目:http://poj.org/problem?id=2279 书上的DP做法会爆内存,尝试写了一个,过了样例. 转载: 代码如下: #include<iostream> #inclu ...

  7. poj2279 Mr. Young's Picture Permutations[勾长公式 or 线性DP]

    若干人左对齐站成最多5行,给定每行站多少个,列数从第一排开始往后递减.要求身高从每排从左到右递增(我将题意篡改了便于理解233),每列从前向后递增.每个人身高为1...n(n<=30)中的一个数 ...

  8. OJ题目分类

    POJ题目分类 | POJ题目分类 | HDU题目分类 | ZOJ题目分类 | SOJ题目分类 | HOJ题目分类 | FOJ题目分类 | 模拟题: POJ1006 POJ1008 POJ1013 P ...

  9. 常规DP专题练习

    POJ2279 Mr. Young's Picture Permutations 题意 Language:Default Mr. Young's Picture Permutations Time L ...

  10. 0x51 线性DP

    数据结构没什么好写的..分块和整体二分还有点分学得很懂..果然我还是比较适合这些东西 poj2279 奇怪题,我的想法就是五维记录最边上的一斜排,会M,结果的的确确是锻炼思维的,正解并不是DP2333 ...

随机推荐

  1. Blazor前后端框架Known-V1.2.2

    V1.2.2 Known是基于C#和Blazor开发的前后端分离快速开发框架,开箱即用,跨平台,一处代码,多处运行. 概述 基于C#和Blazor实现的快速开发框架,前后端分离,开箱即用. 跨平台,单 ...

  2. 华为云河图KooMap 共筑数字孪生底座 共建产业标杆

    摘译:7月7日至9日,华为开发者大会2023(Cloud)将在东莞溪村盛大举行,由华为云河图KooMap带来的关于数字孪生主题的技术分论坛.圆桌闭门会和精彩成果展示 7月7日至9日,华为开发者大会20 ...

  3. python3.8下安装robotframework历险记

    首先非常感谢本文章博主,极大的给与我可以装好的信心(差点要重装python)https://blog.csdn.net/qq_21583077/article/details/107848409?sp ...

  4. 使用C#编写.NET分析器(完结)

    译者注 这是在Datadog公司任职的Kevin Gosse大佬使用C#编写.NET分析器的系列文章之一,在国内只有很少很少的人了解和研究.NET分析器,它常被用于APM(应用性能诊断).IDE.诊断 ...

  5. 加密流量识别检测(一)——在VM虚拟机上搭建指定拓扑

  6. JSGRID loaddata显示超级多空行

    这个逼问题困扰了我两天了 作为一个主后端的程序员 初体验前端技术栈真的麻之又麻 以防万一 请先确认 是不是和我一个情况 如果是 请往下看 首先 我们需要念一段咒语 json是json string是s ...

  7. Oracle随机生成大数据

    Oracle随机插入大数据 话不多说,安排 示例: -- 创建新表并批量插入五千万数据 create table TEST_TAB as select rownum as id, to_char(sy ...

  8. 将Dubbo注册到Nacos,与DubboAdmin的部署

    王有志,一个分享硬核Java技术的互金摸鱼侠加入Java人的提桶跑路群:共同富裕的Java人 本文是<从 0 开始学 Dubbo>系列文章中应用篇的番外篇. 在这篇文章中我会和大家一起部署 ...

  9. java读取txt文件解决乱码问题

    说明:由于txt文件有bom和不同的编码方式,导致导入数据时产生乱码,以下代码完美解决乱码问题. 参考他人代码,结合自己的业务加工完成,费了大半天功夫完成,希望对大家有点用处. 废话不多说,直接上代码 ...

  10. C++函数参数匹配规则

    C++ 函数参数匹配 1 单个参数匹配 void f(); //f1 void f(int); //f2 void f(int, int); //f3 void f(double, double=3. ...