动态规划类题型

法兰要塞(zzulioj周赛7)

题目描述

“分享狼血,与子同胞”
“漫步深渊,心怀正义”
“侍奉光明,斩杀黑暗”
“因剑而生,因剑而死”
“深渊无尽,我等将不娶妻,不生子,只求一世荣耀”
“光阴有时,我等必守此誓,献此生,但愿诸界太平”
无火的余烬,你追随者古老的誓言来到了法兰要塞,为了通过烽火试炼,你必须收集足够多的灵魂。
已知要塞里有n个怪物,不同的怪物有着不同的血量a。每次,你可以选择消灭一只怪物,同时所有血量为a+1和a-1的怪物也会死去。同时你可以获得a个灵魂。

输入

第一行输入一个整数n(1<=n<=10^5)
第二行输入n个整数a1,a2,…an(1<=ai<=10^5)

输出

请输出无火的余烬可以获得的最大灵魂数量

样例输入

9
1 2 1 3 2 2 2 2 3

样例输出

10

分析

对于n个血量的怪物,可以从小到大对其进行动态规划思想。从1开始(因为从单侧开始只需要考虑i+1即可),dp[1][0]为不杀该怪物的灵魂,dp[1][1]为杀该怪物的灵魂。随后分析i+1的dp,即2的dp。由于怪物最大血量为10^5 ,则dp[10^5]即为最终求值

标程

#include<bits/stdc++.h>
using namespace std;
long long soul[100005],s[100005],dp[100005][2];
int main()
{
	int n,a;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a);
		soul[a]+=a;  //soul是指a血的怪物全部杀掉可以获得的灵魂
	}
	for(int i=1;i<=100005;i++)   //此处i指怪物血量 
	{
		dp[i][0]=max(dp[i-1][1],dp[i-1][0]);
		dp[i][1]=dp[i-1][0]+soul[i];
	}
	long long ans=max(dp[100005][1],dp[100005][0]);
	printf("%lld",ans);
}

学长的棒棒糖(zzulioj周赛7)

题目描述

学长有n个棒棒糖,他每次最多可以吃k个,请问他有多少种方法来吃棒棒糖

输入

输入两个整数n, k(1 <= n <= 100000) (1 <= k <= 100)

输出

一个正整数,为不同方法数,由于答案可能很大,你需要输出对答案mod100003的结果。

样例输入

5 2

样例输出

8

提示

8种例子如下:
1-1-1-1-1
2-1-1-1
1-2-1-1
1-1-2-1
1-1-1-2
2-2-1
2-1-2
1-2-2

分析

不太明白为什么要用到dp,目前仅仅只能通过找规律发现规律满足n前k项dp相加之和,如n=5,k=3
dp[5]=dp[4]+dp[3]+dp[2]

标程

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n,k,dp[100005];
	memset(dp,0,sizeof(dp));
	scanf("%d%d",&n,&k);
	dp[0]=1;dp[1]=1;
	for(int i=2;i<=n;i++)
	{
		for(int j=1;j<=k;j++)
		{
			if(i-j<0)
			break;
			dp[i]+=dp[i-j];
			dp[i]=dp[i]%100003;
		}
	}
	printf("%d",dp[n]);
 } 

hdu 1087 Super Jumping! Jumping! Jumping!

现在,有一种象棋游戏叫“超级跳跃!跳跃的!跳跃的!“在HDU非常流行也许你是个好孩子,对这项运动知之甚少,所以我现在就给你介绍一下。
这个游戏可以由两个或两个以上的玩家玩。它由一个棋盘(棋盘)和一些棋子(棋子)组成,所有棋子都用正整数或“开始”或“结束”标记。玩家从起点开始,最后必须跳入终点。在跳跃的过程中,玩家将访问路径中的棋子,但是每个人都必须从一个棋子跳到另一个棋子绝对大(你可以假定起点是最小的,终点是最大的)。所有玩家都不能倒退。一跳可以从一个棋子跳到另一个棋子,也可以跨越许多棋子,甚至你可以直接从起点跳到终点。在这种情况下你当然得零分一个运动员是胜利者,只要他能根据他的跳跃解决方案得到更大的分数。注意,你的分数来自于你跳跃路径中棋子的价值之和。
你的任务是根据给定的棋子列表输出最大值。

Input

输入包含多个测试用例。每个测试用例在一行中描述如下:
N value_1 value_2 …value_N
保证N不大于1000,且所有值均在int范围内。
以0开头的测试用例终止输入,不处理此测试用例。

Output

对于每种情况,按规则打印最大值,一行打印一次。

Sample Input

3 1 3 2
4 1 2 3 4
4 3 3 2 1
0

Sample Output

4
10
3

分析

和法兰要塞思路不同,并没有分开讨论1和0两种情况,思维方式有待提高

#include<iostream>
#include<algorithm>
using namespace std;
int a[1005],dp[1005];
int main()
{
	int n;
	while(scanf("%d",&n)!=EOF && n)
	{
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			dp[i]=a[i];
		}
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<i;j++)
			{
				if(a[i]>a[j])
				dp[i]=max(dp[i],dp[j]+a[i]);
			}
		}
		int ans=0;
		for(int i=1;i<=n;i++)
		ans=max(ans,dp[i]);
		printf("%d\n",ans);
	}
}

LCS

郭哥与瑞瑞在玩一个游戏。

他们先各自写下一串字符,然后互相展示。展示过后,他们再从自己写的那串字符中依次挑出若干字符(保持原有顺序不变),组成新的一串。他们希望自己新组成的字符串与对方新组成的完全相同,并且尽可能长。

例如,郭哥写下abcde,瑞瑞写下aeiou,然后郭哥挑出自己那串里的第1和第5个字符组成新串ae,瑞瑞挑出自己那串中的第1、2个字符,也组成字符串ae。ae就是他们能共同挑出的最长串。

现在,郭哥和瑞瑞分别写出了自己的字符串,请帮他们算一下他们能共同挑出组成的字符串最长有多长。

Input

输入包含多组数据,处理至文件结尾。

每组数据占一行,包括以空格分隔的两个字符串,分别是郭哥和瑞瑞写下的字符串。两个字符串长度都在1000以内。

Output

对于每组输入,输出一个整数,即他们能共同挑出组成的字符串的最大长度。

Sample Input

abcfbc abfcab
programming contest
abcd mnp

Sample Output

4
2
0
在这里插入图片描述
dp[i][j]表示第一个字符串i个字符和第二个j个字符匹配的话可以 截至i和j的位置可以拥有的最大数量

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值