动态规划7--方盒游戏

动态规划7--方盒游戏

一、心得

直接根据问题写状态
如果不能写出状态转移方程,就多维(细化),直至能够写出状态转移方程。

二、题目和分析

题意:
N个方盒(box)摆成一排,每个方盒有自己的颜色。连续摆放的同颜色方盒构成
一个方盒片段(box segment)。下图中共有四个方盒片段,每个方盒片段分别有
1、4、3、1个方盒
玩家每次点击一个方盒,则该方盒所在方盒片段就会消失。若消失的方盒片段

中共有k个方盒,则玩家获得k*k个积分。

思路:区间dp
首先将每个连续颜色的盒子看成一个“块”
click_box(i,j,exlen)代表从i到j以及exlen消除掉可以得到的最高分
exlen表示j右边的“块”,这个块可能不是最初的块,可能是消掉一部分块后形成的
且j的颜色和exlen相同
目标状态: click_box(0,n-1,0)
递推过程
1.直接将j和exlen消除掉
得到click_box(i,j-1,0) + (len[j]+exlen)^2
2.不消除j和exlen,以待以后消除得到更高的分数,贪心啊哈,
更新exlen为len[j]+exlen,假设又和k块颜色相同了(k在i和j之间)

可以得到click_box(i,k,len[j]+exlen) + click_box(k+1,j-1,0)

三、代码

核心代码

 1 /*
 2 动态规划7--方盒游戏
 3 进一步细化之后(复杂化,多维化)
 4 click_box(i,j,ex_len)
 5 表示:
 6 大块j的右边已经有一个长度为ex_len的大块,且j的颜色和ex_len相同,
 7 在此情况下将i到j以及ex_len都消除所能得到的最高分
 8 初始状态: click_box(0,n-1,0)
 9 
10 递推关系:
11 求click_box(i,j,ex_len)时,有两种处理方法,取最优者,
12 假设j与ex_len合并后的大块称作Q
13 1)将Q直接消除,这种做法能得到的最高分就是:
14 click_box(i,j-1,0)+(len[j]+ex_len)^2
15 2) 期待Q以后能和左边的某个同色大块合并。需要枚举可能和W合并的大块。
16 假设让大块k和W合并,则此时能得到的最大分数是:
17 click_box(i,k,len[j]+ex_len)+click_box(k+1,j-1,0) 
18 
19 递归终止条件:
20 i==j
21  
22 */
23 #include <cstring>
24 #include <iostream>
25 using namespace std;
26 struct Block{
27     int color;
28     int len;
29 }; 
30 struct Block segment[200];
31 int score[200][200][200];//记忆化递归,存放计算结果,避免重复计算
32 int click_box(int start,int end,int extra_len){
33     //第一种情况  1)将Q直接消除,这种做法能得到的最高分就是:
34     int i,result,temp;
35     //如果score[start][end][extra_len]被计算过,就直接返回 
36     if(score[start][end][extra_len]>0)
37         return score[start][end][extra_len];
38     result = segment[end].len+extra_len;//这个就是Q
39     //将Q直接消除 
40     result = result*result;//end和extra_len一起消去的得分
41     //头和尾相同了,没得消除的了 
42     if(start==end){//递归终止条件 
43         score[start][end][extra_len]=result;
44         return score[start][end][extra_len]; 
45     } 
46     result += click_box(start,end-1,0);
47     
48     //第一种情况 
49     
50     //------------------------------------------------------------------ 
51     
52     //第二种情况  2) 期待Q以后能和左边的某个同色大块合并。
53     i=end-1;
54     for(i=end-1;i>=start;i--){//从最后往前找和Q颜色相同的方盒 
55         //如果方盒颜色不同,不能合并 
56         if(segment[i].color!=segment[end].color)
57             continue;
58         //下面执行颜色相同的情况
59         //也就是第二种情况 
60         temp=click_box(start,i,segment[end].len+extra_len)+click_box(i+1,end-1,0);
61         if(temp<=result) continue;
62         //如果temp大,那么result变成temp 
63         result=temp; 
64     }
65     
66     //将第一种情况和第二种情况中的较大值返回 
67     score[start][end][extra_len]=result;
68     return score[start][end][extra_len]; 
69 } 
原文地址:https://www.cnblogs.com/Renyi-Fan/p/7057293.html