劳役结合的第四天

菜死我了

我是废物

我是厕所清道夫

大早上把手机带到学校,本来想偷渡到宿舍,但是看别人都交给老师了,我就交了。
今天终于开始推dp了,虽然我能写出来的都是水题。

采花生

题目描述

Hello Kitty想摘点花生送给她喜欢的米老鼠。
她来到一片有网格状道路的矩形花生地(如下图),从西北角进去,东南角出来。
地里每个道路的交叉点上都有种着一株花生苗,上面有若干颗花生,经过一株花生苗就能摘走该它上面所有的花生。
Hello Kitty只能向东或向南走,不能向西或向北走。
问Hello Kitty最多能够摘到多少颗花生。
在这里插入图片描述

输入格式
第一行是一个整数T,代表一共有多少组数据。
接下来是T组数据。
每组数据的第一行是两个整数,分别代表花生苗的行数R和列数 C。
每组数据的接下来R行数据,从北向南依次描述每行花生苗的情况。每行数据有C个整数,按从西向东的顺序描述了该行每株花生苗上的花生数目M。

输出格式

对每组输入数据,输出一行,内容为Hello Kitty能摘到得最多的花生颗数。

样例

输入样例

2
2 2
1 1
3 4
2 3
2 3 4
1 6 5

输出样例

8
16

#include <bits/stdc++.h>
using namespace std;
int a[1010][1010],t,r,c;
int main()
{
    
    
	cin>>t;
	while(t--)
	{
    
    
		cin>>r>>c;
		for(int i=1;i<=r;i++)
		{
    
    
			for(int j=1;j<=c;j++)
			{
    
    
				cin>>a[i][j];
			}
		}
		for(int i=1;i<=r;i++)
		{
    
    
			for(int j=1;j<=c;j++)
			{
    
    
				a[i][j]=max(a[i-1][j]+a[i][j],a[i][j-1]+a[i][j]);
			}
		}
		cout<<a[r][c]<<endl;
	}
	return 0;
}

最低通行费

题目描述

一个商人穿过一个N×N的正方形的网格,去参加一个非常重要的商务活动。
他要从网格的左上角进,右下角出。
每穿越中间1个小方格,都要花费1个单位时间。
商人必须在(2N-1)个单位时间穿越出去。
而在经过中间的每个小方格时,都需要缴纳一定的费用。
这个商人期望在规定时间内用最少费用穿越出去。
请问至少需要多少费用?
注意:不能对角穿越各个小方格(即,只能向上下左右四个方向移动且不能离开网格)。

输入格式

第一行是一个整数,表示正方形的宽度N。
后面N行,每行N个不大于100的整数,为网格上每个小方格的费用。
输出格式
输出一个整数,表示至少需要的费用。

样例

输入样例

5
1 4 6 8 10
2 5 7 15 17
6 8 9 18 20
10 11 12 19 21
20 23 25 29 33

输出样例

109

样例解释

样例中,最小值为109=1+2+5+7+9+12+19+21+33。

#include <bits/stdc++.h>
using namespace std;
int a[1010][1010],f[1010][1010],t,n;
int main()
{
    
    
	cin>>n;
	memset(f,10,sizeof(f));
	f[1][0]=0;f[0][1]=0;
	for(int i=1;i<=n;i++)
	{
    
    
		for(int j=1;j<=n;j++)
		{
    
    
			cin>>a[i][j];
		}
	}
	for(int i=1;i<=n;i++)
	{
    
    
		for(int j=1;j<=n;j++)
		{
    
    
			f[i][j]=min(f[i-1][j]+a[i][j],f[i][j-1]+a[i][j]);
		}
	}
	cout<<f[n][n];
	return 0;
}

方格取数

题目描述

设有 N×N 的方格图,我们在其中的某些方格中填入正整数,而其它的方格中则放入数字0。如下图所示:
在这里插入图片描述

某人从图中的左上角 A 出发,可以向下行走,也可以向右行走,直到到达右下角的 B 点。
在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。
此人从 A 点到 B 点共走了两次,试找出两条这样的路径,使得取得的数字和为最大。

输入格式

第一行为一个整数N,表示 N×N 的方格图。
接下来的每行有三个整数,第一个为行号数,第二个为列号数,第三个为在该行、该列上所放的数。
行和列编号从 11 开始。
一行“0 0 0”表示结束。

输出格式

输出一个整数,表示两条路径上取得的最大的和。

样例

输入样例

8
2 3 13
2 6 6
3 5 7
4 4 14
5 2 21
5 6 4
6 3 15
7 2 14
0 0 0

输出样例

67

#include<bits/stdc++.h>
using namespace std;
int n,s[60][60],f[60][60][60][60],a,b,c;
int main()
{
    
    
	cin>>n;
	while(1)
	{
    
    
		cin>>a>>b>>c;
		if(a==0&&b==0&&c==0) break;
		s[a][b]=c;
	}
	for(int i=1;i<=n;i++)
	{
    
    
		for(int j=1;j<=n;j++)
		{
    
    
			for(int k=1;k<=n;k++)
			{
    
    
				for(int h=1;h<=n;h++)
				{
    
    
					if(i!=k||h!=j)
					{
    
    
						f[i][j][k][h]=max(max(f[i-1][j][k-1][h],f[i][j-1][k-1][h]),max(f[i-1][j][k][h-1],f[i][j-1][k][h-1]))+s[i][j]+s[k][h];
					}
					else f[i][j][k][h]=max(max(f[i-1][j][k-1][h],f[i][j-1][k-1][h]),max(f[i-1][j][k][h-1],f[i][j-1][k][h-1]))+s[i][j];
				}
			}
		}
	}
	cout<<f[n][n][n][n];
	return 0;
}

传纸条

Description

小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题。一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了。幸运的是,他们可以通过传纸条来进行交流。纸条要经由许多同学传到对方手里,小渊坐在矩阵的左上角,坐标(1,1),小轩坐在矩阵的右下角,坐标(m,n)。从小渊传到小轩的纸条只可以向下或者向右传递,从小轩传给小渊的纸条只可以向上或者向左传递。
在活动进行中,小渊希望给小轩传递一张纸条,同时希望小轩给他回复。班里每个同学都可以帮他们传递,但只会帮他们一次,也就是说如果此人在小渊递给小轩纸条的时候帮忙,那么在小轩递给小渊的时候就不会再帮忙。反之亦然。
还有一件事情需要注意,全班每个同学愿意帮忙的好感度有高有低(注意:小渊和小轩的好心程度没有定义,输入时用0表示),可以用一个0-100的自然数来表示,数越大表示越好心。小渊和小轩希望尽可能找好心程度高的同学来帮忙传纸条,即找到来回两条传递路径,使得这两条路径上同学的好心程度只和最大。现在,请你帮助小渊和小轩找到这样的两条路径。

Input Format

输入的第一行有2个用空格隔开的整数m和n,表示班里有m行n列(1<=m,n<=50)。
接下来的m行是一个m*n的矩阵,矩阵中第i行j列的整数表示坐在第i行j列的学生的好心程度。每行的n个整数之间用空格隔开。

Output Format

输出共一行,包含一个整数,表示来回两条路上参与传递纸条的学生的好心程度之和的最大值。

Sample Input

3 3
0 3 9
2 8 5
5 7 0

Sample Output

34

Hint

30%的数据满足:1<=m,n<=10
100%的数据满足:1<=m,n<=50

Limitation

各个测试点1s

#include<bits/stdc++.h>
using namespace std;
int n,m,s[60][60],f[60][60][60][60],a,b,c;
int main()
{
    
    
	cin>>m>>n;
	for(int i=1;i<=m;i++)
		for(int j=1;j<=n;j++)
			cin>>s[i][j];
	for(int i=1;i<=m;i++)
	{
    
    
		for(int j=1;j<=n;j++)
		{
    
    
			for(int k=1;k<=m;k++)
			{
    
    
				for(int h=1;h<=n;h++)
				{
    
    
					if(i!=k||h!=j)
					{
    
    
						f[i][j][k][h]=max(max(f[i-1][j][k-1][h],f[i][j-1][k-1][h]),max(f[i-1][j][k][h-1],f[i][j-1][k][h-1]))+s[i][j]+s[k][h];
					}
					else f[i][j][k][h]=max(max(f[i-1][j][k-1][h],f[i][j-1][k-1][h]),max(f[i-1][j][k][h-1],f[i][j-1][k][h-1]))+s[i][j];
				}
			}
		}
	}
	cout<<f[m][n][m][n];
	return 0;
}

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

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

#include <bits/stdc++.h>
using namespace std;
long long h[8],f[31][31][31][31][31],n;
int main()
{
    
    
	while(1)
	{
    
    
		memset(h,0,sizeof h);
		memset(f,0,sizeof f);
		cin>>n;
		if(n==0) break;
		for(int i=1;i<=n;i++)
		{
    
    
			cin>>h[i];
		}
		f[0][0][0][0][0]=1;
		for(int a=0;a<=h[1];a++)
		{
    
    
			for(int b=0;b<=h[2];b++)
			{
    
    
				for(int c=0;c<=h[3];c++)
				{
    
    
					for(int d=0;d<=h[4];d++)
					{
    
    
						for(int e=0;e<=h[5];e++)
						{
    
    
							if(a<h[1])f[a+1][b][c][d][e]+=f[a][b][c][d][e];
							if(b<a&&b<h[2])f[a][b+1][c][d][e]+=f[a][b][c][d][e];
							if(c<b&&c<h[3])f[a][b][c+1][d][e]+=f[a][b][c][d][e];
							if(d<c&&d<h[4])f[a][b][c][d+1][e]+=f[a][b][c][d][e];
							if(e<d&&e<h[5])f[a][b][c][d][e+1]+=f[a][b][c][d][e];
						}	
					}
				}
			}
		}
		cout<<f[h[1]][h[2]][h[3]][h[4]][h[5]]<<endl;
	}
	return 0;
}

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

#include<bits/stdc++.h>
using namespace std;
const int N=3e3+10;
int a[N],b[N],n,ans,f[N][N];
int main()
{
    
    freopen("test.in","r",stdin);freopen("test.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	for(int i=1;i<=n;i++)
		cin>>b[i];
	for(int i=1;i<=n;i++)
	{
    
    
		ans=0;
		if(b[0]<a[i]) ans=f[i-1][0];
		for(int j=1;j<=n;j++)
		{
    
    
			if(a[i]==b[j])
				f[i][j]=max(f[i][j],ans+1);
			else 
				f[i][j]=f[i-1][j];
			if(b[j]<a[i])
				ans=max(ans,f[i-1][j]);
		}
	}
	ans=0;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			ans=max(ans,f[i][j]);
	cout<<ans;
	return 0;
} 

于是在晚上打AtCoder,自闭了,A题一开始没想double,A和B还都把编译器搞错了,C题过不去卡住了,D题高斯圆还得有偏移量太难了。剩下的都没看到,就开始写文化课作业了。
在这里插入图片描述
由于大早上就把手机交了,晚上决定回宿舍肝作业。

吃得苦中苦,考上985

作业按时交,圆梦211

猜你喜欢

转载自blog.csdn.net/ydsrwex/article/details/113730927