【动态规划】ybt1301 大盗阿福

【题目描述】

 阿福是一名经验丰富的大盗。趁着月黑风高,阿福打算今晚洗劫一条街上的店铺。

这条街上一共有 N 家店铺,每家店中都有一些现金。阿福事先调查得知,只有当他同时洗劫了两家相邻的店铺时,街上的报警系统才会启动,然后警察就会蜂拥而至。

作为一向谨慎作案的大盗,阿福不愿意冒着被警察追捕的风险行窃。他想知道,在不惊动警察的情况下,他今晚最多可以得到多少现金?

【输入】

输入的第一行是一个整数T(T50),表示一共有T组数据。

接下来的每组数据,第一行是一个整数N(1N100,000) ,表示一共有N家店铺。第二行是N个被空格分开的正整数,表示每一家店铺中的现金数量。每家店铺中的现金数量均不超过1000

【输出】

对于每组数据,输出一行。该行包含一个整数,表示阿福在不惊动警察的情况下可以得到的现金数量。

【输入样例】

2
3
1 8 2
4
10 7 6 14

【输出样例】

8
24

【提示】

对于第一组样例,阿福选择第2家店铺行窃,获得的现金数量为8

对于第二组样例,阿福选择第1和4家店铺行窃,获得的现金数量为10+14=24

一道典型的动规题目。先设置状态。设数组value [i]  表示第 i 家店铺的现金数量,dp [i] [0/1] 表示第 i 家店铺的状态,0表示不洗劫这家店铺所能获得的最多现金,1表示洗劫这家店铺所能获得的最多现金。

两种情况:1.第 i  家店铺已经被洗劫了。那么与它相邻的第 i - 1 家店铺不能被洗劫,要不然就会触发警报。所以第 i 家店铺没有被洗劫的状态 dp [i] [0] 继承的是它前面一家店铺被洗劫的状态,同时还要加上洗劫第 i 家店铺获得的现金,也就是 dp [i] [1] = dp [i-1] [0] + value [i] ;

2.第 i 家店铺没有被洗劫。那么第 i - 1 家店铺有可能被洗劫也有可能没有,也就是说 dp [i] [0] 继承的是它的前面的店铺没有被洗劫和有被洗劫的状态,两者取一个最大值即可,即 dp [i] [0] = max ( dp [i-1] [0] , dp [i-1] [1] )。

至于初始状态,那就是 dp [1] [0] = 0 (很明显第一家店铺没有被洗劫,没有获得现金)和 dp [1] [1] = value [1](第一家店铺被洗劫,获得对应现金) 了。

同时要注意数据范围,不能太小,value 至少要开到大于 100,000 。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int dp[100001][2];
int value[100001];
int n,t;//店铺量,数据组数
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        n=read();
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&value[i]);
        }
        dp[1][0]=0;
        dp[1][1]=value[1];
        for(int i=2; i<=n; i++)
        {
            dp[i][0]=max(dp[i-1][0],dp[i-1][1]);
            dp[i][1]=dp[i-1][0]+value[i];
        }
        cout<<max(dp[n][0],dp[n][1])<<endl;
        memset(dp,0,sizeof(dp));//下一组数据
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/jiangyuechen/p/12943658.html