试着用一种新的方法写博客,拿一道题试一试水
(注:题目背景为自己(瞎乱)创作的,和题目本身没有关系)
题目背景:
在遥远的小山村里面,住着一位勇者与他的同伴路由器,然而现在已经是和平年代了,勇者不能再像以前那样探索世界了——因为你需要办理通行的各种手续,而且勇者也不能乱翻别人柜子了,于是勇者失去了他的经济来源,于是迫于生计,他只好去工厂中打工。
厂长kekeke为了测试新来的家伙脑子灵不灵光,将还没有包装的零件交给了勇者,让它来进行分组。
然而勇者好久没有动脑子了,于是他把问题推给了他的同伴路由器来解决。
题目描述 Description
现有一些棍状零件,每个零件都有一定的长度(Li)和重量(Wi)。现在为了加工需要,要将他们分成若干组,使每一组中的零件都能排成一个长度和重量都不下降(若i < j,则Li<=Lj,Wi<=Wj,其中i,j为在同一组中的序号)的序列。请问至少要分成几组?
输入描述 Input Description
第1行为一个整数n,表示棍状零件的总个数。
接下来n行每行有两个正整数,分别为一个零件的长度(Li)和重量(Wi)。
输出描述 Output Description
输出一个正整数,表示最小分成的组数
样例输入 Sample Input
5
8 4
3 8
9 7
2 3
3 5
样例输出 Sample Output
2
n<=1000
Wi<=10000
Li<=10000
路由器开始想用贪心方法,一趟冒泡排序后根据排序结果输出答案。
但是这个问题却暗藏着陷阱,这样贪心是不可以的。
但是路由器好歹能够连上网络,然后各位dalao给出来的答案却十分晦涩难懂:这不就是那道拦截导弹的那道题吗?
(如果不知道拦截导弹的题的小伙伴请baidu一下)
哈!开玩笑,这个题怎么可能…
还真有关系。
(这里为了防止超时用到了快排而非冒泡(虽然不知道是不是会真的超时))
好的路由器在将代码发上来之前来说一下为什么像吧。
首先,我们排序根据长度为第一关键字,重量为第二关键字进行排序。
然后,请想像排好的零件们的顺序为他们现在是第几个
再然后,抛掉长度(因为已经用长度排好序了),将零件改造成导弹,将重量改为导弹的高度。
最后的一步,将分组变成拦截系统,并且将系统改造为(只能一次比一次打的高(或者相等))
怎么样,突然间就明白了吧!
那我就不讲拦截导弹怎么做了(简单说一下,用贪心做最长不下降子序列)
路由器上传代码ing…
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
struct ling{
int l;
int w;
}a[1001];
int ans=0,n,vis[1001]={0};
int comp(ling a,ling b){
if(a.l<b.l)return 1;
if(a.l>b.l)return 0;
if(a.w<b.w)return 1;
return 0;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d %d",&a[i].l,&a[i].w);
}
sort(a+1,a+n+1,comp);
/*
for(int i=1;i<=n;i++){
printf("%d %d\n",a[i].l,a[i].w);
}
*/
for(int i=1;i<=n;i++){
if(vis[i]==1)continue;
int zui=a[i].w;
for(int j=i+1;j<=n;j++){
if(vis[j]==1||a[j].w<zui)continue;
vis[j]=1;
zui=a[j].w;
}
ans++;
}
printf("%d",ans);
return 0;
}