【题目简述】:题目的大概意思就是,现在要在个个房间之间搬桌子,但是只有一条很窄的走廊,每次只能过一个桌子,而且每搬一个桌子要10分钟,所以如果我们要搬的任意两个桌子之间的起点与终点有重合的地方,就要再等10分钟。然后输入要搬几个桌子以及要搬的每个桌子是从哪个房间到哪个房间,问我们最短需要花多少时间。
【分析】:如果区间有重合就要加上额外的10分钟,所以我们只需要算出在哪一段走廊上重合的次数最多,然后用重合的次数乘以10就是我们要求的最短时间。---------------+++当然还有让我收获更大的贪心算法,在下面!!
代码如下:
// 268K 16Ms
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int corrider[401];
int main()
{
int t,N;
int i,j;
int x,y;// 区间x,y。
cin>>t;
while(t--)
{
cin>>N;
memset(corrider,0,sizeof(corrider));
for(i = 0; i<N;i++)
{
cin>>x>>y;
if(x>y)
swap(x,y);
if(x%2==0) // 如果左区间是偶数,就要将其减一,因为此时减一的那个奇数值是与它共用一段走廊
x = x-1;
if(y%2!=0) // 同理,如果右区间是奇数,就要加一。
y = y+1;
for(j = x;j<=y;j++)
corrider[j]++;
}
sort(corrider,corrider+401);
cout<<corrider[400]*10<<endl;
}
return 0;
}
以上的这种做法,只能处理数据量不是很大的问题,如果数据量达到10的9次幂或者更大一点我们用这个便没了办法,不过我们可以尝试另外一种贪心的算法。http://blog.youkuaiyun.com/u012914220/article/details/22326169
#include<stdio.h>
#include<stdlib.h>
struct Table
{
int sta;
int end;
int vist;
};
struct Table table[100005];
int cmp(const void *a,const void *b)
{
return (*(struct Table *)a).sta-(*(struct Table *)b).sta;
}
int main()
{
int test,n,m,i,s,t,times,temp;
scanf("%d",&test);
while(test--)
{
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d%d",&s,&t);
if(s>t)
{
s=s+t;
t=s-t;
s=s-t;
}
table[i].sta=(s+1)/2;
table[i].end=(t+1)/2;
table[i].vist=0;
}
qsort(table,n,sizeof(struct Table),cmp);
temp=0;
times=0;
m=n;
while(m)
{
for(i=0;i<n;i++)
{
if(!table[i].vist&&table[i].sta>temp)
{
temp=table[i].end;
table[i].vist=1;
m--;
}
}
temp=0;
times++;
}
printf("%d\n",times*10);
}
return 0;
}
这个算法主要思想是贪心,我们试着从第一条线段开始依次和其他的比对,如果两个线段没有重合的部分,我们就把它们“合并”,然后再用第二条线段做同样的操作!这样最后我们组合出的线段总数就是一共重合的次数!
为什么这个线段数是最后重合的次数呢??试想如果有线段不和我们归结出的线段重合,它就会在我们第一步的操作中被合并!所以最后组合出的线段总数就是重合的次数!