POJ_1390,三维动规题目,按照大块分类,参考博客,重点:
1.构造递归函数
2.通过三维数组记忆化保存
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
struct Box{
int color,len;
}box[205];
int t,n,x,y,idx,dp[205][205][205];
int click_box(int i,int j,int len){
if(dp[i][j][len])
return dp[i][j][len];
if(i == j)
return dp[i][j][len] = (box[j].len + len) * (box[j].len + len);
dp[i][j][len] = click_box(i,j - 1,0) + (box[j].len + len)*(box[j].len + len);//点击最后一个盒子
for(int k = i;k <= j - 1;k++)
if(box[k].color == box[j].color)
//为什么不是box[k] + len ? box[j].len + len是k右边的大块进行合并的长度,k合不合并分两种,取最优
dp[i][j][len]=max(dp[i][j][len],click_box(i,k,box[j].len+len)+click_box(k+1,j-1,0));
return dp[i][j][len];
}
int main(){
scanf("%d",&t);
for(int i = 1;i <= t;i++){//多组输入的时候初始化一定要注意!!!
scanf("%d",&n);
idx = 0,y = -1;
memset(dp,0,sizeof(dp)); //初始化
memset(box,0,sizeof(box));//初始化
for(int j = 1;j <= n;j++){
scanf("%d",&x);
if(x != y){
idx++;
box[idx].len++;
box[idx].color = x;
y = x;
}
else
box[idx].len++;
}
printf("Case %d: %d\n",i,click_box(1,idx,0));
}
return 0;
}
下侧的代码没有通过记忆化存储的方式,会超时,可以对比下(主要是三维数组的应用)
#include <stdio.h>
#include <iostream>
#include <vector>
using namespace std;
struct block{
int length,color;
};
vector<block> blocks;
int merge(int start,int end,int exlength){
if(start==end) return (blocks[start].length+exlength)*(blocks[start].length+exlength);
vector<int> same_color_id;
for(int i=start;i<end;i++)
if(blocks[i].color==blocks[end].color)
same_color_id.push_back(i);
int score=merge(start,end-1,0)+(blocks[end].length+exlength)*(blocks[end].length+exlength);
for(int i=0;i<same_color_id.size();i++){
int temp_score=merge(start,same_color_id[i],blocks[end].length+exlength) + merge(same_color_id[i]+1,end-1,0);
if(score<temp_score)
score=temp_score;
}
return score;
}
int main() {
int test; cin>>test;
for(int testi=1;testi<=test;testi++){
int num; cin>>num;
int lastcolor=0;
for(int i=0;i<num;i++){
int color; cin>>color;
if(color!=lastcolor){ //分块
block curr_block = {1,color};
blocks.push_back(curr_block);
lastcolor=color;
}
else blocks[blocks.size()-1].length++;
}
printf("Case %d: %d\n",testi,merge(0,blocks.size()-1,0));
blocks.clear();
}
return 0;
}