算法学习2——动态规划 4/2

一些典型题目

1.

2015级数据结构第四次上级F
显然这个题目要用到动态规划,可以考虑假设有n步,每一步都要纠结要不要捡金币,但从后往前考虑,则假设将结果保存在数组 a n s [ n ] ans[n] ans[n]中,每步有多少金币则保存在数组 a [ n ] a[n] a[n]中,则分情况考虑,
1.走到第n步的时候如果捡起金币,则n-1步肯定没有捡起金币,则 a n s [ n ] = a [ n ] + a n s [ n − 2 ] ans[n] = a[n] + ans[n-2] ans[n]=a[n]+ans[n2]
2.走到第n步的时候选择不捡起金币,则结果 a n s [ n ] = a n s [ n − 1 ] ans[n] = ans[n-1] ans[n]=ans[n1]
所以要想得到最大的值,递归式为: a n s [ n ] = m a x { a [ n ] + a n s [ n − 2 ] , a n s [ n − 1 ] } ans[n] = max\{a[n] + ans[n-2], ans[n-1]\} ans[n]=max{a[n]+ans[n2],ans[n1]}
得到下面代码:

//递归求解 
#include <cstdio>

int max(int a, int b) {
	return (a>b)?a:b;
}

int dp(int a[], int n){
	if(n == 0) return 0;
	if(n == 1) return a[0];
	return max(a[n-1] + dp(a, n-2), dp(a, n-1));
}

int main() {
	int n;
	while(~scanf("%d", &n)) {
		int a[100], i, j, target;
		for(i = 0; i < n; i++) scanf("%d", &a[i]);
		scanf("%d", &target);
		if(dp(a, n) >= target) printf("AZY is back, baby!\n");
		else printf("Poor AZY!\n");		
	}
	return 0;
} 

of course,这种方法实在是太慢了
下面就是动态规划啦

//自上而下,带备忘录方法 
#include <cstdio>
int max(int a, int b) {
	return (a>b)?a:b;
}
int dp(int a[], int ans[], int n){
	int p;
	if(n == 0) return 0;
	if(ans[n-1] > 0) return ans[n-1];
	p  = max(a[n-1] + dp(a, ans, n-2), dp(a, ans, n-1));
	ans[n-1] = p;
	return p;
}
int main() {
	int n;
	while(~scanf("%d", &n)) {
		int a[100], i, target, ans[100];
		for(i = 0; i < n; i++) {
			scanf("%d", &a[i]);
			ans[i] = -1;
		}
		ans[0] = a[0];	
		scanf("%d", &target);
		if(dp(a, ans, n) >= target) printf("AZY is back, baby!\n");
		else printf("Poor AZY!\n");		
	}
	return 0; 
} 

当然啦,最好的写法肯定是这个

//自下而上的求解 
#include <cstdio>
int max(int a, int b) {
	return (a>b)?a:b;
}
int dp(int a[], int ans[], int n){
	int i;
	for(i = 2; i <= n; i++) ans[i] = max(ans[i-2] + a[i], ans[i-1]);
	return ans[n];
}
int main() {
	int n;
	while(~scanf("%d", &n)) {
		int a[100] = {0}, i, target, ans[100] = {0};
		for(i = 1; i <= n; i++) scanf("%d", &a[i]);
		ans[1] = a[1];
		scanf("%d", &target);
		if(dp(a, ans, n) >= target) printf("AZY is back, baby!\n");
		else printf("Poor AZY!\n");		
	}
	return 0;
} 

额,让我试试能不能把重构解写出来,可以输出选择的方法,即选择的哪些步骤的金币。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值