中国海洋大学第四届朗讯杯高级组 The Urge to Merge

本文深入探讨了信息技术领域的各个方面,包括前端开发、后端开发、移动开发、游戏开发、大数据开发等。文章详细介绍了各领域的核心技术、开发工具和关键概念,旨在帮助开发者全面了解并深入掌握信息技术的各个细分领域。

The Urge to Merge

Time Limit: 1000MS Memory limit: 65536K

题目描述

The Acme Consulting Group has sent you into a new technology park to enhance dynamism, synergy and sustainability. You\'re not sure what any of these terms mean, but you\'re pretty good at making money, which is what you plan on doing. The park consists of a 3 × n grid of facilities. Each facility houses a start-up with an inherent value. By facilitating mergers between neighboring start-ups, you intend to increase their value, thereby allowing you to fulfill your life-long dream of opening your own chain of latte-and-burrito shops.

Due to anti-trust laws, any individual merger may only involve two start-ups and no start-up may be involved in more than one merger. Furthermore, two start-ups may only merge if they are housed in adjacent facilities (diagonal doesn\'t count). The added value generated by a merger is equal to the product of the values of the two start-ups involved. You may opt to not involve a given start-up in any merger, in which case no added value is generated. Your goal is to find a set of mergers with the largest total added value generated. For example, the startup values shown in the figure on the left, could be optimally merged as shown in the figure on the right for a total added value of 171.
                                   

输入

 The first line of each test case will contain a single positive integer n 1000 indicating the width of the facilities grid. This is followed by three lines, each containing n positive integers (all  100) representing the values of each start-up. A line containing a single 0 will terminate input.

输出

 For each test case, output the maximum added value attainable via mergers for that set of start-ups.

示例输入

4
7  2  4  9
3  5  9  3
9  5  1  8
0

示例输出

Case 1: 171

提示

 

来源

 中国海洋大学第四届朗讯杯高级组


http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2725

当时比赛的时候看到这道题觉得是道DP,但是因为没有重视高度为3这个条件,想不明白从左上到右下该怎么推,也就没再多考虑。

后来重看这个题,发现整个递推过程只需要从左往右即可。整个dp过程也不难。

以第i列结束的使用的方块,一共有11种形态。不同形态可以从第i-2,第i-1的不同形态转移。

一开始有个地方漏了一点以至于狂WA不止,后来终于发现才AC了。。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[1005][15];
int grid[5][1005];
int n;
int Convers(int v,int a)
{
    switch(v)
    {
    case 1:
        return grid[1][a-1]*grid[1][a];
    case 2:
        return grid[2][a-1]*grid[2][a];
    case 3:
        return grid[3][a-1]*grid[3][a];
    case 4:
        return grid[2][a-1]*grid[2][a]+grid[3][a-1]*grid[3][a];
    case 5:
        return grid[1][a-1]*grid[1][a]+grid[3][a-1]*grid[3][a];
    case 6:
        return grid[1][a-1]*grid[1][a]+grid[2][a-1]*grid[2][a];
    case 7:
        return grid[1][a-1]*grid[1][a]+grid[2][a-1]*grid[2][a]+grid[3][a-1]*grid[3][a];
    case 8:
        return grid[1][a]*grid[2][a];
    case 9:
        return grid[2][a]*grid[3][a];
    case 10:
        return grid[1][a-1]*grid[1][a]+ grid[2][a]*grid[3][a];
    case 11:
        return grid[3][a-1]*grid[3][a]+ grid[1][a]*grid[2][a];
    }
}
int main()
{
    int kase=0;
    while(scanf("%d",&n)==1&&n)
    {
        memset(grid,0,sizeof(grid));
        for(int i=1; i<=3; ++i)
            for(int j=1; j<=n; ++j)
                scanf("%d",&grid[i][j]);
        memset(dp,0,sizeof(dp));
        for(int i=1; i<=n; ++i)
        {
            for(int j=1; j<=11; ++j)
            {
                int res=0;
                if(i>1)
                {
                    switch(j)
                    {
                    case 1:
                        res=max(res,max(dp[i-1][2],max(dp[i-1][3],max(dp[i-1][4],dp[i-1][9]))));
                        break;
                    case 2:
                        for(int k=1; k<=11; ++k)
                            res=max(res,dp[i-2][k]);
                        res=max(res,max(dp[i-1][1],max(dp[i-1][3],dp[i-1][5])));
                        break;
                    case 3:
                        res=max(res,max(dp[i-1][1],max(dp[i-1][2],max(dp[i-1][6],dp[i-1][8]))));
                        break;
                    case 4:
                        res=max(res,dp[i-1][1]);
                        for(int k=1; k<=11; ++k)
                            res=max(res,dp[i-2][k]);
                        break;
                    case 5:
                        res=max(res,dp[i-1][2]);
                        for(int k=1; k<=11; ++k)
                            res=max(res,dp[i-2][k]);
                        break;
                    case 6:
                        res=max(res,dp[i-1][3]);
                        for(int k=1; k<=11; ++k)
                            res=max(res,dp[i-2][k]);
                        break;
                    case 7:
                        for(int k=1; k<=11; ++k)
                            res=max(res,dp[i-2][k]);
                        break;
                    case 8:
                        for(int k=1; k<=11; ++k)
                            res=max(res,dp[i-1][k]);
                        break;
                    case 9:
                        for(int k=1; k<=11; ++k)
                            res=max(res,dp[i-1][k]);
                        break;
                    case 10:
                        res=max(res,max(dp[i-1][2],max(dp[i-1][3],max(dp[i-1][4],dp[i-1][9]))));
                        break;
                    case 11:
                        res=max(res,max(dp[i-1][1],max(dp[i-1][2],max(dp[i-1][6],dp[i-1][8]))));
                        break;
                    }
                }
                if(i==1)
                {
                    if(j==8||j==9)
                        dp[i][j]=Convers(j,i);
                    else
                        dp[i][j]=0;
                }
                else
                    dp[i][j]=res+Convers(j,i);
            }
        }
        int ans=0;
        for(int i=1; i<=11; ++i)
            ans=max(dp[n][i],ans);
        printf("Case %d: ",++kase);
        printf("%d\n",ans);
    }
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值