POJ_1390(三维动规)

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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值