20220705

目录

一.复习动态规划

二.get到了新的知识---赋值问题

三.今日小结


一.复习动态规划

 例题1
数字三角形
题目描述
观察下面的数字金字塔。

写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。

      7 
     3   8 
    8   1   0 
   2   7   4   4 
   4   5   2   6   5
在上面的样例中,从7 到 3 到 8 到 7 到 5 的路径产生了最大

输入格式
第一个行包含 R(1<= R<=1000) ,表示行的数目。

后面每行为这个数字金字塔特定行包含的整数。

所有的被供应的整数是非负的且不大于100。

输出格式
单独的一行,包含那个可能得到的最大的和。

样例数据
input

5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
output

30
 

分析:动态规划入门题,要想找到整体最优解,则需要使上一步为最优解,故状态转移方程为dg[i][j]=max(dg[i-1][j],dg[i-1][j-1])+n[i][j];

#include<bits/stdc++.h>
using namespace std;
int r;
int n[1100][1100],dg[1100][1100];
int main()
{
	freopen("numtri.in","r",stdin);
	freopen("numtri.out","w",stdout);
	cin>>r;
	for(int i=1;i<=r;i++)
	 for(int j=1;j<=i;j++)
	  cin>>n[i][j];
	dg[1][1]=n[1][1];
	for(int i=2;i<=r;i++)
	{
		for(int j=1;j<=i;j++)
		{
			dg[i][j]=max(dg[i-1][j],dg[i-1][j-1])+n[i][j];
		}
	}
	int ans=0;
	for(int i=1;i<=r;i++) ans=max(ans,dg[r][i]);
	cout<<ans<<endl;
	return 0; 	
} 

注:此方法为顺推,及由[1][1]开始

例题2
摘花生
题目描述

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

分析:本题与第一题相似。只需要注意初始化即可。状态转移方程为:dp[i][j]=max(dp[i-1][j],dp[i][j-1])+n[i][j];

#include<bits/stdc++.h>
using namespace std;
int t,r,c;
int ans[1100]={};
int a[1100][1100],dp[1100][1100];
int main()
{
	freopen("peanut.in","r",stdin);
	freopen("peanut.out","w",stdout);
	cin>>t;
	for(int i=1;i<=t;i++)
	{
		memset(a,0,sizeof(a));
		memset(dp,0,sizeof(dp));
		cin>>r>>c;
		for(int j=1;j<=r;j++)
		{
			for(int k=1;k<=c;k++)
			{
				cin>>a[j][k];
			}
		}
		dp[r][c]=a[r][c];
		for(int j=r;j>=1;j--)
		{
			for(int k=c;k>=1;k--)
			dp[j][k]=max(dp[j+1][k],dp[j][k+1])+a[j][k];
		}
		cout<<dp[1][1]<<endl;
	}
	return 0;
}
//dp[i][j]=max(dp[i-1][j],dp[i][j-1])+n[i][j];


注:本题方法为逆推,及从结束点倒退到[1][1],相比较于顺推而言,最大的优点在于直接输出dp[1][1]即可。

例题3
公交乘车
题目描述
一个特别的单行街道在每公里处有一个汽车站。顾客根据他们乘坐汽车的公里使来付费。例如下表就是一个费用的单子。

公里数    1    2    3    4    5    6    7    8    9    10
价格    12    21    31    40    49    58    69    79    90    101
没有一辆车子行驶超过10公里,一个顾客打算行驶n公里()1<=n<=100),它可以通过无限次的换车来完成旅程。最后要求费用最少。

输入格式
第一行十个整数分别表示行走1到10公里的费用(<=500)。注意这些数并无实际的经济意义,即行驶10公里费用可能比行驶一公里少。

第二行一个整数n表示,旅客的总路程数。

输出格式
仅一个整数表示最少费用。

样例数据
input

12 21 31 40 49 58 69 79 90 101
15
output

147
 

分析:状态转移方程:dp[i]=min(dp[i-j]+a[j],dp[i]);   

#include<bits/stdc++.h>
using namespace std;
int cost,n;
int a[550],dp[550];
int main()
{
	freopen("buses.in","r",stdin);
	freopen("buses.out","w",stdout);
	for(int i=1;i<=10;i++) cin>>a[i];
	cin>>n;
	memset(dp,10,sizeof(dp));
	dp[0]=0;
	dp[1]=a[1];
	for(int i=2;i<=n;i++)
	{
		for(int j=1;j<=i&&j<=10;j++)
		{
			dp[i]=min(dp[i-j]+a[j],dp[i]);
		}
	}
	cout<<dp[n]<<endl;
	return 0;
}

二. get到了新的知识---赋值问题

题目描述

在很多程序设计语言中,忘记给变量赋初值的错误常令人头疼。

在下面的问题中,最开始仅有变量a中有确定的值。变量为单个小写字母, 每行恰好有三个字符,中间一个是赋值运算符'='。

请编程求出含N行的程序段运行以后有哪些变量中有确定的值。

输入格式

第一行:N (0<N<=10^6) 以下N行,每行3个字符,为一条语句.

输出格式

如果没有,输出 none 否则在一行中按字母表顺序给出所有有确定值的变量名,字母之间用空格分隔。

样例数据

input

4
b=a
c=d
d=b
e=f

output

a b d

分析:若将输入的三个字符分别定义为x,equal,y,那么分以下三种情况:

1.x有值,y有值,则操作后x,y均有值

2.x有值,y没有值,则操作后x,y均没有值

3.x没有值,y有值,则操作后x,y均没有值

那么对于这三种情况我们要特别注意第二条

考虑周全后,代码实现就很简单了

#include<bits/stdc++.h>
using namespace std;
int sum=0;
int f[220];
int main()
{
	freopen("evaluate1.in","r",stdin);
	freopen("evaluate1.out","w",stdout);
    f[97]=1;
	char a,b,c;
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a>>b>>c;
		if(f[int(c)]==1) f[int(a)]=1;
		if(f[int(c)]!=1) f[int(a)]=0;
	}
	for(int i=97;i<=120;i++)
	{
		if(f[i]==1)
		{
			sum++;
			if(sum==1) cout<<char(i);
			else cout<<' '<<char(i);
		}
	}
	if(sum==0) cout<<"none"<<endl;
	return 0;
}

ps:yyx太强了!

三.今日小结

集训第一天,总体来说比较轻松拉~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值