poj2279
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 5841 | Accepted: 1860 |
Description
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
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
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的更多相关文章
- POJ2279 Mr Young's Picture Permutations
POJ2279 Mr Young's Picture Permutations 描述: 有N个学生合影,站成左对齐的k排,每行分别有N1,N2…NK个人,第一排站最后,第k排站之前.学生身高依次是1… ...
- 【题解】POJ2279 Mr.Young′s Picture Permutations dp
[题解]POJ2279 Mr.Young′s Picture Permutations dp 钦定从小往大放,然后直接dp. \(dp(t1,t2,t3,t4,t5)\)代表每一行多少人,判断边界就能 ...
- 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 ...
- poj2279 线性dp
#include<iostream> #include<cstdio> #include<cstring> #define ll long long using n ...
- POJ2279杨氏矩阵+钩子定理
题目:http://poj.org/problem?id=2279 有dp做法,但会MLE. dp的思想很好,是通过 “按身高由小到大往进放” 把 “身高小于” 的条件转化成 “放进去的先后” ,于是 ...
- poj2279排队——杨氏矩阵与钩子公式(DP爆内存)
题目:http://poj.org/problem?id=2279 书上的DP做法会爆内存,尝试写了一个,过了样例. 转载: 代码如下: #include<iostream> #inclu ...
- poj2279 Mr. Young's Picture Permutations[勾长公式 or 线性DP]
若干人左对齐站成最多5行,给定每行站多少个,列数从第一排开始往后递减.要求身高从每排从左到右递增(我将题意篡改了便于理解233),每列从前向后递增.每个人身高为1...n(n<=30)中的一个数 ...
- OJ题目分类
POJ题目分类 | POJ题目分类 | HDU题目分类 | ZOJ题目分类 | SOJ题目分类 | HOJ题目分类 | FOJ题目分类 | 模拟题: POJ1006 POJ1008 POJ1013 P ...
- 常规DP专题练习
POJ2279 Mr. Young's Picture Permutations 题意 Language:Default Mr. Young's Picture Permutations Time L ...
- 0x51 线性DP
数据结构没什么好写的..分块和整体二分还有点分学得很懂..果然我还是比较适合这些东西 poj2279 奇怪题,我的想法就是五维记录最边上的一斜排,会M,结果的的确确是锻炼思维的,正解并不是DP2333 ...
随机推荐
- ArcPy批量对大量遥感影像相减做差
本文介绍基于Python中ArcPy模块,对大量栅格遥感影像文件批量进行相减做差的方法. 首先,我们来明确一下本文的具体需求.现有一个存储有多张.tif格式遥感影像的文件夹,其中每一个遥感影像 ...
- 自己动手实现rpc框架(二) 实现集群间rpc通信
自己动手实现rpc框架(二) 实现集群间rpc通信 1. 集群间rpc通信 上一篇博客中MyRpc框架实现了基本的点对点rpc通信功能.而在这篇博客中我们需要实现MyRpc的集群间rpc通信功能. 自 ...
- 使用C#编写.NET分析器(三)
译者注 这是在Datadog公司任职的Kevin Gosse大佬使用C#编写.NET分析器的系列文章之一,在国内只有很少很少的人了解和研究.NET分析器,它常被用于APM(应用性能诊断).IDE.诊断 ...
- C补充
C语言之unsigned 与signed 无符号与有符号数据的操作区别在于当最高位,当最高位为0时都一样: 在C中,默认的基础数据类型均为signed,现在我们以char为例,说明(signed) c ...
- 【go语言】1.2.1 Go 环境安装
Go 语言的安装过程非常简单,无论你使用的是哪种操作系统,都可以按照下面的步骤来进行. Windows 系统 前往 Go 语言的官方下载页面:https://golang.org/dl/ 根据你的操作 ...
- clickhouse 与 zookeeper
目录 clickhouse 设置中的 zookeeper 配置 参数说明 配置示例 [预发生产] ClickHouse Keeper 四字母命令 clickhouse 设置中的 zookeeper 配 ...
- Redis从入门到放弃(1):安装配置
1. 介绍 Redis是一个高性能的开源key-value数据库.它被广泛应用于缓存.会话存储.实时分析.消息队列等场景.Redis具有以下三个主要特点: 数据持久化:Redis支持将内存中的数据保存 ...
- FPGA学习之乒乓操作
乒乓操作学习记录如下: 乒乓操作" 是一个常常应用于数据流控制的设计思想, 典型的乒乓操作方法如下图 所示: 乒乓操作的处理流程为:输入数据流通过" 输入数据选择单元"将 ...
- Hi3798MV200 恩兔N2 NS-1 (一): 设备介绍和刷机说明
目录 Hi3798MV200 恩兔N2 NS-1 (一): 设备介绍和刷机说明 Hi3798MV200 恩兔N2 NS-1 (二): 制作 Ubuntu rootfs Hi3798MV200 恩兔N2 ...
- 操作过滤器—MVC中使用操作过滤器实现JWT权限认证
前言 上一篇文章分享了授权过滤器实现JWT进行鉴权,文章链接:授权过滤器-MVC中使用授权过滤器实现JWT权限认证,接下来将用操作过滤器实现昨天的JWT鉴权. 一.什么是操作过滤器? 与授权过滤器 ...