zoukankan      html  css  js  c++  java
  • P1133 教主的花园 (动态规划)

    题目描述

    教主有着一个环形的花园,他想在花园周围均匀地种上n棵树,但是教主花园的土壤很特别,每个位置适合种的树都不一样,一些树可能会因为不适合这个位置的土壤而损失观赏价值。

    教主最喜欢 3种树,这3种树的高度分别为 10,20,30。教主希望这一圈树种得有层次感,所以任何一个位置的树要比它相邻的两棵树的高度都高或者都低,并且在此条件下,教主想要你设计出一套方案,使得观赏价值之和最高。

    输入输出格式

    输入格式:

    第一行为一个正整数 n ,表示需要种的树的棵树。

    接下来 n 行,每行 3 个不超过 10000的正整数 $$a_i,b_i,c_i$$ ,按顺时针顺序表示了第 i 个位置种高度为 10,20,30 的树能获得的观赏价值。

    第 i个位置的树与第 i+1 个位置的树相邻,特别地,第 1 个位置的树与第 n 个位置的树相邻。

    输出格式:

    一个正整数,为最大的观赏价值和。

    输入输出样例

    输入样例#1:

    4
    1 3 2
    3 1 2
    3 1 2
    3 1 2

    输出样例#1:

    11

    说明

    【样例说明】

    第 1 至 n 个位置分别种上高度为 20,10,30,10 的树,价值最高。

    【数据规模与约定】

    对于 20%的数据,有 n≤10 ;

    对于 40% 的数据,有 n≤100;

    对于 60% 的数据,有 n≤1000 ;

    对于 100% 的数据,有 4≤n≤100000 ,并保证 n 一定为偶数。

    Solution

    这道题的思路蛮好想的,只是稍微多了一些限制条件.


    状态定义:

    [f[i][j][k] ]

    表示当前 i 这个点, i-1 的选择为 j , 然后 i 的选择为 k.


    状态转移
    枚举当前这个的点的 j 和 k,然后判断 j 和 k 的大小关系.
    如 : $$ f[i][j][k] $$其中 j>k
    则有前驱状态:

    [f[i-1][1...j-1][j] ]

    其他亦可依次类推.

    但是需要注意最后一个节点和第一个节点的大小关系区分.
    为此,我们可以直接枚举一重 head.
    然后在里面循环的时候注意判断最后一个节点即可.


    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100008;
    int f[maxn][4][4];
    int c[maxn][4],n;
    int ans=-1,head;
    int main()
    {
        ios::sync_with_stdio(false);
        cin>>n;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=3;j++)
        cin>>c[i][j];
        for(head=1;head<=3;head++)
        {
            memset(f,0,sizeof(f));
            f[2][head][1]=c[1][head]+c[2][1];
            f[2][head][2]=c[1][head]+c[2][2];
            f[2][head][3]=c[1][head]+c[2][3];
            for(int i=3;i<=n;i++)
            {
                for(int j=1;j<=3;j++)
                for(int k=1;k<=3;k++)
                {
                    if(j==k)continue;
                    else
                    {
                       if(i==n)
                        {
                          if(k==head)continue;
                          if(j>k&&k>head)continue;
                          if(j<k&&k<head)continue;              
                        }
                        if(j>k)
                            for(int l=1;l<j;l++)
                                f[i][j][k]=max(f[i][j][k],f[i-1][l][j]+c[i][k]);
                        else
                            for(int l=j+1;l<=3;l++)
                                f[i][j][k]=max(f[i][j][k],f[i-1][l][j]+c[i][k]);
                    }
                }   
            }
            for(int i=1;i<=3;i++)
            for(int j=1;j<=3;j++)
            ans=max(f[n][i][j],ans);
        }
        cout<<ans<<endl;
        return 0;
    }
    
  • 相关阅读:
    Sparrow 开发板化身电脑音量调节器
    我的第一台台式机
    DFRobot万物互联大赛第二轮
    DFRobot万物互联大赛第一轮
    RPi Cam v2 之一:基础及牛刀小试
    Galileo Gen2 之MQTT通讯
    路飞学城Python爬虫课第一章笔记
    Micro:Bit手柄试用之一MagicPad (解决蓝牙与gamePad包共存)
    PocketBeagle 初高级设置
    EVB-P6UL:一识庐山真面目
  • 原文地址:https://www.cnblogs.com/Kv-Stalin/p/9123197.html
Copyright © 2011-2022 走看看