poj 1390 dp(方盒游戏)
2015-07-30 21:35
253 查看
题意:N个方盒(box)摆成一排,每个方盒有自己的颜色。连续摆放的同颜色方盒构成一个方盒片段(box segment)。比如共有四个方盒片段,每个方盒片段分别有 1、4、3、1个方盒,玩家每次点击一个方盒,则该方盒所在方盒片段就会消失。若消失的方盒片段中共有k个方盒,则玩家获得k*k个积分。问给定游戏开始时的状态,玩家可获得的最高积分是多少?
思路:首先进行预处理:将连续的若干个方块作为一个“大块”(box_segment) 考虑,假设开始一共有 n个“大块”,编号0到n-1,第i个大块的颜色是color[i],包含的方块数目,即长度,是len[i]。
首先尝试如果用click_box(i,j)表示从大块i到大块j这一段消除后所能得到的最高分,那么考虑最后一个大块j是自己删除还是和左边的某一个同色大块一起删除,似乎可以得到:click_box(i,j) = MAX{click_box(i,j-1) + len[j]*len[j] , click_box(i,k-1) + click_box(k+1,j-1) + (len[k]+len[j])2}。但是这样的想法是错误的,因为将大块k和大块j合并后,形成的新大块会在最右边。将该新大块直接将其消去的做法,才符合上述式子,但直接将其消去,未必是最好的,也许它还应该和左边的同色大块合并,才更好。所以上述求得的不是最有解。
那么此时考虑增加一维,考虑新的形式:click_box(i,j,ex_len),表示大块j的右边已经有一个长度为ex_len的大块(该大块可能是在合并过程中形成的,不妨就称其为ex_len),且j的颜色和ex_len 相同,在此情况下将 i 到j以及ex_len都消除所能得到的最高分。于是整个问题就是求:click_box(0,n-1,0)。
求click_box(i,j,ex_len)时,有两种处理方法,取最优者。假设j和ex_len合并后的大块称作 Q
1) 将Q直接消除,这种做法能得到的最高分就是: click_box(i,j-1,0) + (len[j]+ex_len)2
2) 期待Q以后能和左边的某个同色大块合并。需要枚举可能和Q 合并的大块。假设让大块k和Q合并,则此时能得到的最大分数是:
click_box(i,k,len[j]+ex_len) + click_box(k+1,j-1,0)。
click_box(i,j,ex_len) 的终止条件是i == j。
dp采用记忆化搜索的形式:
思路:首先进行预处理:将连续的若干个方块作为一个“大块”(box_segment) 考虑,假设开始一共有 n个“大块”,编号0到n-1,第i个大块的颜色是color[i],包含的方块数目,即长度,是len[i]。
首先尝试如果用click_box(i,j)表示从大块i到大块j这一段消除后所能得到的最高分,那么考虑最后一个大块j是自己删除还是和左边的某一个同色大块一起删除,似乎可以得到:click_box(i,j) = MAX{click_box(i,j-1) + len[j]*len[j] , click_box(i,k-1) + click_box(k+1,j-1) + (len[k]+len[j])2}。但是这样的想法是错误的,因为将大块k和大块j合并后,形成的新大块会在最右边。将该新大块直接将其消去的做法,才符合上述式子,但直接将其消去,未必是最好的,也许它还应该和左边的同色大块合并,才更好。所以上述求得的不是最有解。
那么此时考虑增加一维,考虑新的形式:click_box(i,j,ex_len),表示大块j的右边已经有一个长度为ex_len的大块(该大块可能是在合并过程中形成的,不妨就称其为ex_len),且j的颜色和ex_len 相同,在此情况下将 i 到j以及ex_len都消除所能得到的最高分。于是整个问题就是求:click_box(0,n-1,0)。
求click_box(i,j,ex_len)时,有两种处理方法,取最优者。假设j和ex_len合并后的大块称作 Q
1) 将Q直接消除,这种做法能得到的最高分就是: click_box(i,j-1,0) + (len[j]+ex_len)2
2) 期待Q以后能和左边的某个同色大块合并。需要枚举可能和Q 合并的大块。假设让大块k和Q合并,则此时能得到的最大分数是:
click_box(i,k,len[j]+ex_len) + click_box(k+1,j-1,0)。
click_box(i,j,ex_len) 的终止条件是i == j。
dp采用记忆化搜索的形式:
#include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <queue> #include <cstdlib> using namespace std; #define INF 0x3fffffff #define clc(s,t) memset(s,t,sizeof(s)) #define N 205 int T,n,q=1; int dp ,s ,len ,c ; int solve(int a,int b,int x){ if(dp[a][b][x]) return dp[a][b][x]; if(a == b) return dp[a][b][x] = (len[a]+x)*(len[a]+x); dp[a][b][x] = solve(a,b-1,0)+(len[b]+x)*(len[b]+x); for(int i = b-2;i>=a;i--) if(c[i]==c[b]) dp[a][b][x] = max(dp[a][b][x],solve(a,i,len[b]+x)+solve(i+1,b-1,0)); return dp[a][b][x]; } int main(){ scanf("%d",&T); while(T--){ int i,j; clc(dp,0); scanf("%d",&n); for(i = 0;i<n;i++) scanf("%d",&s[i]); for(i = 0,j=-1;i<n;i++){ if(i && s[i]==s[i-1]){ len[j]++; continue; } c[++j] = s[i]; len[j] = 1; } solve(0,j,0); printf("Case %d: %d\n",q++,dp[0][j][0]); } return 0; }
相关文章推荐
- 拓扑排序
- Symmetric Tree
- 在 eclipse 上安装 genymotion 插件不成功的解决办法
- Mac OSX 上 Android Studio 编译使用 JAVA8 及 retrolambda 的项目出错解决方案
- 黑马程序员----java基础面向对象总结
- Openssl摘要算法接口函数使用
- 黑马程序员---iOS基础---C语言中的预处理命令
- FTP服务器访问方法
- 66. Plus One
- 重复登录脚本修改02
- 我的第一篇博文
- Leetcode Q11:Container With Most Water
- c++ 控制台流和字符串流
- 嵌入式软件开发——汇顶 笔试 一面 二面
- IOS--UI--LessonGCD
- POJ 2513--Colored Sticks【字典树编号 && 并查集判连通 && 无向图欧拉路】
- WinEdt和LaTeX的简介
- c++ 控制台流和字符串流
- Yougth的最大化(好题,二分查找 0 1分数规划)
- JNI编程(一) —— 编写一个最简单的JNI程序