poj 1390:Blocks 方盒游戏

总时间限制:
5000ms
内存限制:
65536kB

描述
Some of you may have played a game called ‘Blocks’. There are n blocks in a row, each box has a color. Here is an example: Gold, Silver, Silver, Silver, Silver, Bronze, Bronze, Bronze, Gold.
The corresponding picture will be as shown below:

这里写图片描述

If some adjacent boxes are all of the same color, and both the box to its left(if it exists) and its right(if it exists) are of some other color, we call it a ‘box segment’. There are 4 box segments. That is: gold, silver, bronze, gold. There are 1, 4, 3, 1 box(es) in the segments respectively.

Every time, you can click a box, then the whole segment containing that box DISAPPEARS. If that segment is composed of k boxes, you will get k*k points. for example, if you click on a silver box, the silver segment disappears, you got 4*4=16 points.

Now let’s look at the picture below:
这里写图片描述
The first one is OPTIMAL.

Find the highest score you can get, given an initial state of this game.
输入
The first line contains the number of tests t(1<=t<=15). Each case contains two lines. The first line contains an integer n(1<=n<=200), the number of boxes. The second line contains n integers, representing the colors of each box. The integers are in the range 1~n.
输出
For each test case, print the case number and the highest possible score.
样例输入

2
9
1 2 2 2 2 3 3 3 1
1
1

样例输出

Case 1: 29
Case 2: 1

大概意思是说,有这样一个游戏,就是,第一个图那样,好多盒子,然后,打其中一个盒子,那些和这个盒子同个颜色并且相邻的盒子都和这个盒子一起消失,并且得到 消失的盒子的个数的平方 分。。问,如何才能得到最多分(类似与祖玛游戏)

Emmm。。。这道题和前面的灌溉草场,个人认为,还是这道题难啊,怎么老师会说这道题的比灌溉草场简单,哎,肯定是我的悟性不够。。。。。以下解题思路来自《算法基础与在线实践》一书和众网友的解题报告

这道题是这样做的:刚开始的时候,将输入的盒子按照颜色相同的盒子放为一类,类里面有这个类的颜色和这个类有多少个盒子。。比如第一附图,那么block[0].color=1,block[0].len=1;block[1].color=2,block[1].len=4;block[2].color=3,block[2].len=3;block[3].color=1,block[3].len=1。

然后,对于dp(l, r, len)的意思是,在条件 “区间[l, r]里并且后面有连续len个盒子和在r位置的盒子同颜色的盒子” 下,得到最高的分数是多少。注意,这里的条件是说,r后面有连续len个盒子和它同颜色,因为,在中间的不同颜色的盒子已经被消去了。

那么,对于dp(l,r,len)就有下面两个方法可以得到结果,也就是要取这两个方法的最大值。

dp(l,r,len) = max( dp(l, r-1, 0)+(ex_len+n_v[r].len)*(ex_len+n_v[r].len), dp(l, k, ex_len+n_v[r].len)+dp(k+1, r-1, 0))

dp(l, r-1, 0)+(ex_len+n_v[r].len)*(ex_len+n_v[r].len) 是说,直接把r和r后面的ex_len个盒子都消去,得到的分数。

dp(l, k, ex_len+n_v[r].len)+dp(k+1, r-1, 0) 是说,找到中间一个k个块,它和r的颜色是相同的,那么,就把k个块和r和ex_len一起消去,就是dp(l, k, ex_len+n_v[r].len),加上把k和r中间的那部分消去的分数,就是dp(k+1, r-1, 0),这里对于每个情况,又会有两个递归,就可以向前遍历所有可能情况了。

代码如下:

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
struct block{
    int color;  //这个块的颜色
    int len;  //这个块的大小
    block(int _color, int _len):color(_color), len(_len){};
};
vector<block> n_v;
int info[200][200][200];
int dp(int l, int r, int ex_len){
    if(info[l][r][ex_len]>0) return info[l][r][ex_len];
    if(l==r) return (n_v[l].len+ex_len)*(n_v[l].len+ex_len);
    int temp = dp(l, r-1, 0)+(ex_len+n_v[r].len)*(ex_len+n_v[r].len);
    for (int k = r-1; k >= l ; k--) {
        if(n_v[k].color == n_v[r].color){
            //找到一个合适的了
            temp = max(temp, dp(l, k, ex_len+n_v[r].len)+dp(k+1, r-1, 0));
        }
    }
    info[l][r][ex_len] = temp;
    return temp;
}
int main()
{
    int t, c=1;
    cin>>t;    //多少个测试用例
    while(t--){
        memset(info, 0, sizeof(info));
        n_v.clear();
        int n;     //多少个盒子
        cin>>n;
        int num;
        cin>>num;
        n_v.push_back(block(num, 1));
        for (int i = 1; i < n; ++i) {
            cin>>num;
            if(num==(n_v.end()-1)->color){
                //和上一个颜色块的颜色一样,放到同一个结构体里面
                (n_v.end()-1)->len++;
            }
            else{
                //颜色不同,新加一个结构体元素
                n_v.push_back(block(num, 1));
            }
        }
        cout<<"Case "<<c++<<": "<<dp(0, n_v.size()-1, 0)<<endl;
    }
    return 0;
}
/*
2
9
1 2 2 2 2 3 3 3 1
1
1
*/

这里写图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值