• POJ2228 Naptime 环形DP


    题目大意:牛在第i个小时睡觉能够恢复U[i]点体力。睡觉时第一小时不恢复体力。一天的N小时连着下一天的1小时。求能够恢复体力的和的最大值。

    定义DP[i][j][0]为前i个小时休息了j个小时,i小时不休息,DP[i][j][1]为休息。

    如果不考虑N小时连着下一天的1小时,则有递归式:

    DP[i][j][0] = max(DP[i - 1][j][0], DP[i - 1][j][1]);
    if (j > 0)
        DP[i][j][1] = max(DP[i - 1][j - 1][0], DP[i - 1][j - 1][1] + U[i]);

    初值为F[1][0][0](第一小时不睡觉)=DP[1][1][1](第一小时刚开始睡)=0,其余负无穷。终值为max(DP[N][B][0],DP[N][B][1])

    剩下的只有第一小时在熟睡的情况了,只需把初值改为DP[1][1][1]=U[1](一小时在熟睡),终值改为DP[N][B][1](不管N时是在熟睡还是浅睡,必须是在睡觉)。

    两种情况取最大值即可。

    注意:

    • DP时要用滚动数组,否则会超内存
    • 仔细看看初值与终值。
    • 打完代码必须肉眼检查,像把i写成i-1的错误。
    • 共用的innerDP不要两个函数里分别写,有不便于修改等缺点。
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int MAX_N = 4000, MAX_B = MAX_N;
    int N, B;
    int U[MAX_N];
    int DP[2][MAX_B][2];
    
    void innerDp()
    {
    	for (int i = 2; i <= N; i++)
    	{
    		memset(DP[i & 1], 0xcf, sizeof(DP[i & 1]));
    		for (int j = 0; j <= i; j++)
    		{
    			DP[i & 1][j][0] = max(DP[i - 1 & 1][j][0], DP[i - 1 & 1][j][1]);
    			if (j > 0)
    				DP[i & 1][j][1] = max(DP[i - 1 & 1][j - 1][0], DP[i - 1 & 1][j - 1][1] + U[i]);
    		}
    	}
    }
    
    int DP1()
    {
    	memset(DP, 0xcf, sizeof(DP));
    	DP[1][0][0] = DP[1][1][1] = 0;
    
    	innerDp();
    	return max(DP[N&1][B][0], DP[N&1][B][1]);
    }
    
    
    int DP2()
    {
    	memset(DP, 0xcf, sizeof(DP));
    	DP[1][1][1] = U[1];
    
    	innerDp();
    	return DP[N&1][B][1];
    }
    
    int main()
    {
    #ifdef _DEBUG
    	freopen("c:\noi\source\input.txt", "r", stdin);
    #endif
    	scanf("%d%d", &N, &B);
    	for (int i = 1; i <= N; i++)
    		scanf("%d", i + U);
    	int a = DP1();
    	//printf("%d
    ", a);
    	int b = DP2();
    	//printf("%d
    ", b);
    	printf("%d
    ", max(a, b));
    	return 0;
    }
    

      

  • 相关阅读:
    yum与rpm常用命令
    centos7更改时区,同步时间
    剑指Offer45:扑克牌顺子(java)
    剑指Offer44:翻转单词顺序列(java)
    剑指Offer43:左旋转字符串(Java)
    剑指Offer42:和为S的两个数字(java)
    剑指Offer41:和为S的连续正数序列(Java)
    剑指Offer39:平衡二叉树(Java)
    剑指Offer40:数组中只出现一次的数字(Java)
    剑指Offer38:二叉树的深度(Java)
  • 原文地址:https://www.cnblogs.com/headboy2002/p/8545354.html
Copyright © 2020-2023  润新知