1 条题解
-
0
大概意思是说,有这样一个游戏,就是,第一个图那样,好多盒子,然后,打其中一个盒子,那些和这个盒子同个颜色并且相邻的盒子都和这个盒子一起消失,并且得到 消失的盒子的个数的平方 分。。问,如何才能得到最多分(类似与祖玛游戏)
这道题是这样做的:刚开始的时候,将输入的盒子按照颜色相同的盒子放为一类,类里面有这个类的颜色和这个类有多少个盒子。。比如第一附图,那么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; }
- 1
信息
- ID
- 391
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者