线性DP总结

本文整理了12道线性动态规划(DP)题目,包括Mr.Youngs Picture Permutations、LCIS、修路Making the Grade等,涵盖了数组、最长上升子序列、最优化问题等多个主题。每道题目提供了输入输出格式、样例数据和分析,适合用于锻炼和提高DP解题能力。
摘要由CSDN通过智能技术生成

顺序

  • 1.Mr.Youngs Picture Permutations
  • 2.LCIS
  • 3.修路Making the Grade
  • 4.Mobile Service
  • 5.传纸条
  • 6.I-country
  • 7.Cookies
  • 8.逆序对数列
  • 9.乌龟棋
  • 10.养猪
  • 11.赶吃花的牛
  • 12.花园

持续更新中……

第一次更新,复制了9道题目,打了框架,和一些简单的题目
第二次更新,又一次赋值貌似和dp无关的三题,及前二题的代码,修了前面一些部分坑


1. Mr.Youngs Picture Permutations

题目描述

杨老师希望给他的班级拍一张合照。

学生们将站成左端对齐的多排,靠后的排站的人数不能少于靠前的排。
XXXXX
XXX
XXX
X.

如下所示:例如,12名学生可以排成5,3,3和1名学生的行(从后到前)。

此外,杨先生希望每排学生安排高度从左到右减少。此外,学生的身高应该从后面降到前面。考虑到这一点,杨先生认为,对于12个学生的例子,至少有两种方式来安排学生(1个作为最高等):

1 2 3 4 5    1 5 8 11 12
6 7 8       2 6 9
9 10 11     3 7 10
12          4

杨先生想知道对于给定的行排列,可能有多少不同的学生安排。他尝试用3,2和1行开始手工计数,并计算16种安排:

在这里插入图片描述

杨先生认为手工计数对任何合理数量的学生都不会非常有效,因此他要求您通过编写计算机程序来帮助确定给定行集的学生的不同安排的数量。

输入格式

每个问题实例的输入将包含两行。第一行给出行数k,作为十进制整数。第二行包含从后到前(n1,n2,…,nk)的行的长度,作为由单个空格分隔的十进制整数。问题集以行数为0结束。行数永远不会超过5行,学生总数N(行长度之和)最多为30。

输出格式

每个问题实例的输出应该是N个学生在给定行中的排列数,以便高度沿着每一行从左到右沿着每一列从后到前逐渐减小为十进制整数。(假设所有高度都是不同的。)每个问题实例的结果应该在一个单独的行上。将选择输入数据,以使结果始终适合无符号的32位整数。

样例数据
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

output

1
1
16
4158
141892608
9694845

数据规模与约定
时间限制:1s
1s
空间限制:65536KB
65536KB

分析:

没什么可以分析,蓝皮书上写有(算法竞赛指南(很好的书~))
在这里插入图片描述
因为在合法的合影方案中每行,每列身高都是单调的
所以当每排一名新生时,考虑所有满足如下条件的行数i:
1.ai<Ni
2.i=1或ai-1>ai

可以设F[a1,a2,a3,a4,a5]表示各排从左端起分别站了a1,a2,a3,a4,a5个人时,合影的方案数。

边界为:F[0,0,0,0,0]=1,其余均为0;
目标:F[N1,N2,N3,N4,N5];

详情见代码~
{ 在这里插入图片描述}

#include<bits/stdc++.h>
using namespace std;
const int N=300;
long long n,m,i,j,l,k,o;
long long a[N],b[N];
int main()
{
   
//	freopen("i.in","r",stdin);
//	freopen("i.out","w",stdout);
	scanf("%lld",&n);
    while(n!=0)
    {
   
	   for(memset(a,0,sizeof(a)),i=0;++i<=n;)scanf("%lld",&a[i]);
	   long long f[a[1]+1][a[2]+1][a[3]+1][a[4]+1][a[5]+1];
	   memset(f,0,sizeof(f));
	   f[0][0][0][0][0]=1;
       if(n==1)printf("1\n");
       else 
	   {
   
	        for(i=-1;++i<=a[1];)
              for(j=-1;++j<=a[2];)
                for(l=-1;++l<=a[3];)
                  for(k=-1;++k<=a[4];)
                    for(o=-1;++o<=a[5];)
                    {
   
                      m=f[i][j][l][k][o];
					  if(i<a[1])f[i+1][j][l][k][o]+=m;
					  if(j<a[2]&&j<i)f[i][j+1][l][k][o]+=m;
					  if(l<a[3]&&l<j)f[i][j][l+1][k][o]+=m;
					  if(k<a[4]&&k<l)f[i][j][l][k+1][o]+=m;
					  if(o<a[5]&&o<k)f[i][j][l][k][o+1]+=m;
					}
	    
	       printf("%lld\n",f[a[1]][a[2]][a[3]][a[4]][a[5]]);
	   } 
       scanf("%lld",&n);	
	}
	
	
    return 0;	
}

2.LCIS

Description

熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目。小沐沐先让奶牛研究了最长上升子序列,再让他们研究了最长公共子序列,现在又让他们要研究最长公共上升子序列了。

小沐沐说,对于两个串A,B,如果它们都包含一段位置不一定连续的数字,且数字是严格递增的,那么称这一段数字是两个串的公共上升子串,而所有的公共上升子串中最长的就是最长公共上升子串了。

奶牛半懂不懂,小沐沐要你来告诉奶牛什么是最长公共上升子串。不过,只要告诉奶牛它的长度就可以了。

Input Format

第一行N,表示A,B的长度。

第二行,串A。

第三行,串B。

Output Format

输出长度。

Sample Input

4
2 2 1 3
2 1 2 3

Sample Output

2

Hint
1<=N<=3000,A,B中的数字不超过maxlongint
Limitation
各个测试点1s

F[i,j]表示A1到Ai和B1到Bi可以构成Bj为结尾的LCIS的长度
A0=B0=-∞
当Ai≠Bj时,有f[i,j]=f[i-1,j]
当Ai=Bj
F [ i , j ] = m a x ( f [ i − 1 , k ] ) + 1 = m a x ( F [ i − 1 , k ] ) + 1 F[i,j]=max ({f[i-1,k]})+1=max({F[i-1,k]})+1 F[i,j]=max(f[i1,k])+1=max(F[i1,k])+1

优化:
把满足0≦k<j,Bk<Ai的k构成的集合称为F[i,j]进行状态转移时的决策方案,记为S(i,j)
S ( i , j + 1 ) = S ( i , j ) B j ≧ A i /   S ( i , j ) ∪ j B j &lt; A i S(i,j+1)={S(i,j) B_j≧A_i}{ /~S(i,j)∪{j} B_j&lt;A_i}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值