您的位置:首页 > 其它

CCF1301 大盗阿福(动规练习题)

2017-12-26 16:55 120 查看
题目:☞点击这里☜

思路:根据题目我们发现阿福不能偷相连的店铺,也就是说阿福能偷到的价值等于前面第二个店铺或前面第三个店铺,为什么不算前面第四个店铺呢,以为前面第四个店铺其实就相当于前面第二个店铺的前面的第二个店铺。有点乱吧?看下面解释:

我们现在假设有6个店铺,每个店铺的价值为

1 2 3 4 5 6

我们总是从第一个或第二个偷起,为什么呢?因为你偷第三个就相当于你先偷第一个再偷第三个了。

而且我们每偷到一个店铺,那么我们就只能偷下下个或者是下下下个,如果偷下一个(相当于偷了连续的),阿福就会被逮捕,前面说了阿福不想被逮捕,所以也就不能偷下一个。

举个例子,比如阿福偷到第一个店铺,那么他只能偷第三个店铺或第四个店铺,而不能偷第二个店铺。如果偷第五个店铺,也就相当于先偷第三个再偷第五个了,显然这比偷第五个店铺更优。所以只需要考虑后面第二个或第三个了。

但由于顺推比较麻烦,所以这里采用逆推。

动态转移方程:

f[i]=max(f[i],max(f[i-2]+a[i],f[i-3]+a[i]));
代码
评测记录链接


#include<cstdio>
#define r(i,a,b) for (int i=a;i<=b;i++)//循环
using namespace std;
int f[100001],n,t,a[100001];
int max(int x,int y){return x>y?x:y;}
void read(int &f)//输入流,598ms比第二快了524ms。就是靠这个刷到了第一。
{
f=0;char c;
while (c=getchar(),c>='0'&&c<='9') f=f*10+c-48;//没有负数所以可以不用考虑符号,直接加进去
}
void write(int x)//输出流
{
if (x) write(x/10);else return;
putchar(x%10+48);
}
int main()
{
read(t);//t组数据
r(i,1,t)
{

read(n);//n个数
r(i,1,n)
{read(a[i]);f[i]=0;}//输入
f[1]=a[1];f[2]=max(a[2],f[1]);f[3]=f[1]+a[3];//第一个的最优值就是a[1],第二个的最优值要么是a[1],要么是a[2],第三个的最优值只有可能是f[1]的值+a[3]
r(i,3,n)
f[i]=max(f[i],max(f[i-2]+a[i],f[i-3]+a[i]));//动态转移
write(max(f
,f[n-1]));if (i!=t)putchar(10);//因为最后偷的要么是偷到最后一个,要么是倒数第二个,取其中最大值,后面的语句是去掉最后的换行。
}
}


a445
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: