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个。
在往深扩展一步,我们可以发现上下两串数字中如果有相同的数字,那么可以找到一个恰当的位置(位置就是以它们所在序号为坐标,参照上面)放正方体。
到这里,答案已经呼之欲出了。聪明的你到这里可以试着写一下。
题目特别长,背景我就不赘述了。讲下大概题目意思。
题目意思是给你一个立体图形的正视图,和侧视图,问你用小正方体达成这样的效果最小个数。结合题目中的图看下,就能知道意思了。
输入数据:
每一行先输入立体的长和宽(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;
}