【C - Monkey and Banana】

80 篇文章 0 订阅
80 篇文章 0 订阅

思路:

  • 最长上升子序列的变种。
  • 数字改成了结构体 BLOCK,并且不仅要求出长度,本题需要求出最高的高度。
  • 每个 BLOCK 都是无限的,因此每块都可以变成六块。然后按底面的长排序(贪心),正方形 dp 求解。
  • 注意 ans 的使用(dp[i] 的意义)。

代码:

  • 核心:正方形 dp 求解最长上升子序列
#include <iostream>
#include <algorithm>

using namespace std;

int main(){
	int num[9] = {2 ,7, 1, 5, 6, 4 ,3 ,8 ,9};
	int dp[9];
	for(int i=0;i<9;i++){
		dp[i] = 1;
		for(int j=0;j<i;j++){
			if(num[i] > num[j]){
				dp[i] = max(dp[i] , dp[j] + 1);
			}
		}
		cout<<dp[i]<<endl;
	}
}
  • 0ms 1388kB
//0ms		1388kB 


#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn = 35 * 6 + 5; 

int T = 0;
int N;
int ans;
int dp[maxn];
struct BLOCK{
	int a,b,c;
	friend bool operator <(BLOCK l , BLOCK r)
	{
		return l.a == r.a ? l.b < r.b : l.a < r.a ;//实际上因为要求a、b都严格递增,并不需要判断b
	}
}block[maxn];int cnt;
void ADDBLOCK(int a,int b,int c){
	block[cnt].a = a;
	block[cnt].b = b;
	block[cnt].c = c;
	++cnt;
	return ;
}

void INIT(){
	cnt = 0;
	ans = 0;
	return ;
}

int main(){
	while(~scanf("%d" , &N) && N){
		++T;
		INIT();
		while(N--){
			int a,b,c;
			scanf("%d%d%d" , &a , &b , &c);
			ADDBLOCK(a,b,c);
			ADDBLOCK(a,c,b);
			ADDBLOCK(b,a,c);
			ADDBLOCK(b,c,a);
			ADDBLOCK(c,a,b);
			ADDBLOCK(c,b,a);
		}
		sort(block , block+cnt);//因为可以随意使用方块,相当于原序列不是序列而是集合(无序),所以排序,相当于是贪心的思想
		for(int i=0;i<cnt;i++){
			dp[i] = block[i].c;
			for(int j=0;j<i;j++)
				if(block[i].a > block[j].a && block[i].b > block[j].b)
					dp[i] = max(dp[i] , dp[j] + block[i].c);
			ans = max(ans , dp[i]);//千万不要忘,dp[i]是有限制条件的,必须使用block[i],它不一定是全局最优解。 
		}
		printf("Case %d: maximum height = %d\n" , T , ans);
	}
	return 0;
}

二刷:

  • 15ms 1388kB
//15ms		1388kB


#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 33;

int T; 
int N;
struct NODE{
	int x,y;
	int z;
	friend bool operator < (NODE a , NODE b)
	{
		if(a.x == b.x)
			return a.y > b.y;
		return a.x > b.x;
	}
}node[maxn * 6];int cnt;
void ADDNODE(int x,int y,int z){
	node[cnt].x = x;
	node[cnt].y = y;
	node[cnt].z = z;
	++cnt;
	return ;
}
struct DP{
	int A,B;
	int height;
}dp[maxn * 6];

int main(){
	while(cin>>N && N){
		cnt = 0;
		memset(dp , 0 , sizeof(dp));
		for(int i=1;i<=N;i++){
			int x,y,z;
			cin>>x>>y>>z;
			ADDNODE(x,y,z);
			ADDNODE(x,z,y);
			ADDNODE(y,x,z);
			ADDNODE(y,z,x);
			ADDNODE(z,x,y);
			ADDNODE(z,y,x);
		}
		sort(node , node + cnt);
		int MAX = 0;
		for(int i=0;i<cnt;i++){			
			int j;
			int place_id = 0;
			int place_height = 0;
			for(j=i-1;j>=0;j--)
				if(dp[j].A > node[i].x && dp[j].B > node[i].y)
					if(dp[j].height > place_height){
						place_height = dp[j].height;
						place_id = j;
					}
			//注意,这里需要完全遍历! 
			if(place_id)
				dp[i].height = place_height + node[i].z;
			else
				dp[i].height = node[i].z;
			dp[i].A = node[i].x;
			dp[i].B = node[i].y;
			MAX = max(MAX , dp[i].height);
		}
		printf("Case %d: maximum height = %d\n" , ++T , MAX);
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值