T1227 大盗阿福
41.31% 1000ms 65536K
题目描述
阿福是一名经验丰富的大盗。趁着月黑风高,阿福打算今晚洗劫一条街上的店铺。
这条街上一共有 N
家店铺,每家店中都有一些现金。阿福事先调查得知,只有当他同时洗劫了两家相邻的店铺时,街上的报警系统才会启动,然后警察就会蜂拥而至。
作为一向谨慎作案的大盗,阿福不愿意冒着被警察追捕的风险行窃。他想知道,在不惊动警察的情况下,他今晚最多可以得到多少现金?
输入格式
输入的第一行是一个整数 T(T≤50) ,表示一共有 T 组数据。
接下来的每组数据,第一行是一个整数 N (1≤N≤100,000),表示一共有 N 家店铺。
第二行是 N 个被空格分开的正整数,表示每一家店铺中的现金数量。每家店铺中的现金数量均不超过 1000。
输出格式
对于每组数据,输出一行。
该行包含一个整数,表示阿福在不惊动警察的情况下可以得到的现金数量。
提示
对于第一组样例,阿福选择第 2 家店铺行窃,获得的现金数量为 8。对于第二组样例,阿福选择第 1 和 4 家店铺行窃,获得的现金数量为 10 + 14 = 24。
样例输入
2
3
1 8 2
4
10 7 6 14
样例输出
8
24
问题分析
opt[i]:到下标为i的最佳方案
由于样例输入太短,不方便分析,所以,重新写一个数组 m[] = {1,2,4,1,7,8,3}
我的分析有些简单,有不明白的大家可以去b站看博主 正月点灯笼 的 ‘动态规划(第2讲)’视频。
代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 100000
int m[N]; //存放每家店铺的现金金额
int dp_maxM(int m[], int n){
int dp_opt[n]; //存放最优子解
int A,B,res; //A,B分别接收两种不同情况的结果,res为最后的解
//初始化
dp_opt[0] = m[0];
dp_opt[1] = max(m[0],m[1]);
res = m[0];
for(int i=2; i<n; i++){
//寻找最优子解
A = dp_opt[i-2] + m[i];
B = dp_opt[i-1];
dp_opt[i] = max(A, B);
}
for(int i=1; i<n; i++){
//在最优子解中找到最优解
if(res < dp_opt[i])
res = dp_opt[i];
}
return res;
}
int main(){
int T,n;
cin >> T;
for(int i=0; i<T; i++){
cin >> n;
for(int j=0; j<n; j++){
cin >> m[j];
}
cout << dp_maxM(m,n) << endl;
}
return 0;
}