POJ 3802 Cubist Artwork(思维题)

POJ 3802
题目特别长,背景我就不赘述了。讲下大概题目意思。
题目意思是给你一个立体图形的正视图,和侧视图,问你用小正方体达成这样的效果最小个数。结合题目中的图看下,就能知道意思了。
输入数据:
每一行先输入立体的长和宽(n*m),也就是长就是正视图的长,宽就是正视图的长。
然后输入正视图每一列的最大高度,侧视图每一行的最大高度。


这一道题目不考什么算法,主要考思维。
首先确定一个原则,要让最后需要的小正方体最小,那么每个小正方体最好都能对正视图和侧视图做出贡献。
由此可以发现,放在n*m对角线上的正方体对正视图和侧视图都有影响。
就拿第一组样例举例子
5 5
1 2 3 4 5 最优的结果就是把15个小正方体分为1,2,3,4,5这五组,按照顺序放
1 2 3 4 5 在对角线上,这样的解是最优的。


5 5 再来看这一组样例
2 5 4 1 3 咋一看,不能按照上面的策略来做。但其实实质是一样的,尽可能让
4 1 5 3 2 每个正方体对正视图和侧视图有贡献。
这一个样例中,我们看到正视图中有5,侧视图中也有5,那么我们想办法把这两个凑在一起。聪明的你一定可以发现,在(3,2)(第三列,第二行)放上5个正方体就可以达成目的
同样的,我们可以在(1,3)放上4个正方体,在(4,5)放上3个正方体。。。等等
最后有5个恰当的位置都可以放上1,2,3,4,5个正方体,达成效果。
所以最小也只需要15个。

在往深扩展一步,我们可以发现上下两串数字中如果有相同的数字,那么可以找到一个恰当的位置(位置就是以它们所在序号为坐标,参照上面)放正方体。

到这里,答案已经呼之欲出了。聪明的你到这里可以试着写一下。


解题思路:首先找出上面相同的数字,在找有多少对。这个数字只需要加(成对的个数+成单的个数)次,如果找不到成对的数字,就只需要加一次就可以了。

如果你觉得这篇博客帮助了你,请顶一下或关注。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<functional>
#include<algorithm>
using namespace std;
int a[25],b[25];//存储输入数据
int cnt1[25],cnt2[25];//用来找成对数字
int n,m;
int main()
{
	int i,k,ans,num;
	while(scanf("%d%d",&n,&m),n&&m)
	{
		k=ans=num=0;
		memset(cnt1,0,sizeof(cnt1));
		memset(cnt2,0,sizeof(cnt2));//清空操作
		for(i=0;i<n;i++)
		{
			scanf("%d",&a[i]);
			cnt1[a[i]]++;
		}
		for(i=0;i<m;i++)
		{
			scanf("%d",&b[i]);
			cnt2[b[i]]++;
		}//输入数据
		for(i=1;i<=20;i++)//每个数字最多为20
		{
			k=abs(cnt1[i]-cnt2[i]);//成单的个数
			num=min(cnt1[i],cnt2[i]);//成对的个数
			ans+=(i*num+i*k);
			//printf("i=%d k=%d num=%d ans=%d\n",i,k,num,ans);
		}
		printf("%d\n",ans);
	}
	return 0;
}





  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值