一些典型题目
1.
显然这个题目要用到动态规划,可以考虑假设有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[n−2]
2.走到第n步的时候选择不捡起金币,则结果
a
n
s
[
n
]
=
a
n
s
[
n
−
1
]
ans[n] = ans[n-1]
ans[n]=ans[n−1]
所以要想得到最大的值,递归式为:
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[n−2],ans[n−1]}
得到下面代码:
//递归求解
#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;
}
额,让我试试能不能把重构解写出来,可以输出选择的方法,即选择的哪些步骤的金币。