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 ...
随机推荐
- 使用Ajax进行数据请求
一.Ajax开源库有很多选择,大家可以根据需求自己选择 jQuery:jQuery是一个广泛应用的JavaScript库,它提供了简洁而强大的API来处理Ajax请求.通过$.ajax()方法或其 ...
- 2023CCPC大学生程序设计竞赛-nhr
新生菜菜第一次参加这种大型比赛,还是有点紧张的,CCPC我们队就A了三题,铜牌.第一道,以为是签到,然后就交给clk了,我和crf看下一道过的题比较多的,然后感觉是一个滑动窗口,另一道题是纯数学公式. ...
- linux 查看进程使用的内存大小
你可以使用 ps 命令结合 grep 命令来查看进程使用的内存大小.以下是示例代码: ps aux | grep <进程名> 这个命令会列出所有匹配 <进程名> 的进程,并显示 ...
- NativeBuferring——一种零分配的数据类型[上篇]
之前一个项目涉及到针对海量(千万级)实时变化数据的计算,由于对性能要求非常高,我们不得不将参与计算的数据存放到内存中,并通过检测数据存储的变化实时更新内存的数据.存量的数据几乎耗用了上百G的内存,再加 ...
- 从 HTTP/1.1 到 HTTP/3
从 HTTP/1.1 到 HTTP/3,解决了一些旧协议的问题,引入了好用的新功能. HTTP/1.1 HTTP/1.1 通过在传输层和应用层之间增加 SSL/TSL 解决数据不安全的问题,但它本身还 ...
- 不要再傻傻分不清 hash、 chunkhash 和 contenthash 啦
hash.contenthash 和 chunkhash 是通过散列函数处理之后,生成的一串字符,可用于区分文件. 文件名不带哈希值 webpack.config.js 文件中,output 中定义输 ...
- nginx反向代理常用基本配置
http反向代理 http { ... server { listen 80; location / { proxy_pass http://192.1 ...
- frp内网穿透环境搭建--服务端ubuntu 客户端win10
前提条件:1个公网ip服务器,例如我的是腾讯云服务器ubuntu20 下载frp软件,下的是0.33.0版本,该版本直接把软件封装成服务,能用ubuntu直接定义开机自启等 github:https: ...
- Programming abstractions in C阅读笔记:p123-p126
<Programming Abstractions In C>学习第50天,p123-p126,总结如下: 一.技术总结 1.notaion 这也是一个在计算机相关书籍中出现的词,但有时却 ...
- DDD实践:实现基于快照机制的变更追踪
王有志,一个分享硬核Java技术的互金摸鱼侠 加入Java人的提桶跑路群:共同富裕的Java人 去年我们在重构项目中落地了DDD,当时花了点时间研究了下阿里巴巴大淘宝技术发布的<阿里技术专家详解 ...