问题说明
ACM著名(高级电脑制造商)公司租了地面建筑,其形状如下图所示。
楼有200间客房,每沿着走廊的北侧和南侧。最近公司做了一个计划,以改革其系统。改革包括房间之间的表动了不少。由于楼道狭窄,所有的表都是大的,只有一个表可以通过走廊。有些计划需要使移动高效。经理想通了以下计划:将表从一个房间到另一个房间,可以在10分钟内完成。当从一个房间移动表i到J室,部分前面房间之间的走廊上,我和J室的前面。所以,在此期间,每10分钟,一些移动的同时进行两个房间之间不共享相同的部分的走廊。要清楚经理说明了可能的情况下,不可能的情况下同时移动。
每间客房,最多一个表将被移动或移动。现在,经理寻求以最少的时间,将所有表的方法。你的任务是写一个程序,以解决经理人的问题。
楼有200间客房,每沿着走廊的北侧和南侧。最近公司做了一个计划,以改革其系统。改革包括房间之间的表动了不少。由于楼道狭窄,所有的表都是大的,只有一个表可以通过走廊。有些计划需要使移动高效。经理想通了以下计划:将表从一个房间到另一个房间,可以在10分钟内完成。当从一个房间移动表i到J室,部分前面房间之间的走廊上,我和J室的前面。所以,在此期间,每10分钟,一些移动的同时进行两个房间之间不共享相同的部分的走廊。要清楚经理说明了可能的情况下,不可能的情况下同时移动。
每间客房,最多一个表将被移动或移动。现在,经理寻求以最少的时间,将所有表的方法。你的任务是写一个程序,以解决经理人的问题。
题解:此题有两种方法:方法一:由于n太小,可以用一种最简单的解法:即每走一次就对走过的走廊加1,然后遍历一边找出最大的覆盖值;和树状数组有点相似;
方法二:先对起点排序,然后判断这些线段是否可以和其他的线段放在一排,不能放在一排单放在一排,flag值就加1;
注意:1:起点与终点的大小要先比较大小,因为可以有类似这种情况40-——30;
2:奇偶房间对称,共用一个走廊,所以要先对s和e进行奇偶判断,奇数就加一;
代码实现:
方法一:
#include<iostream> using namespace std; int main() { int M; cin>>M; while(M--) { int i,n,k,l; //l个需要搬动的桌子,起始n,中止k cin>>l; int id[201]={0}; while(l--) { cin>>n>>k; if(n>k) {i=n;n=k;k=i;} //交换小值n在前 for(i=(n+1)/2;i<=(k+1)/2;i++) //奇数偶数全加一然后除以2就是走廊号。 id[i]++; } int max=0; for(i=0;i<201;i++) if(max<id[i]) max=id[i]; //找覆盖的最大值 cout<<max*10<<endl; } return 0; }
方法二:
#include<stdio.h>
#include<cstring>
#include<algorithm>
using namespace std;
#pragma comment(linker,"/STACK:102400000,102400000")
#define MAX 205
struct line1
{
int s,e;
}line[MAX];
int sign[MAX];//为标记可以放在一排的最后的终点位置;
bool cmp(line1 x,line1 y)
{
return(x.s<y.s);
}//对起点进行排序
int main()
{
//freopen("input.txt","r",stdin);
int i,j,t,n,x,y;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
memset(sign,-1,sizeof(sign));//标记要初始化为-1,因为起点可能是0;
for(i=0;i<n;i++)
{
scanf("%d%d",&x,&y);
if(x%2)x+=1;//走廊是奇偶房间公用的
if(y%2)y+=1;
line[i].s=x>y?y:x;//起点与终点的大小进行比较
line[i].e=x>y?x:y;
}
sort(line,line+n,cmp);//排序
int flag=0;//标记最大的可以排成多少排
for( i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(line[i].s>sign[j])
{
sign[j]=line[i].e;
if(j+1>flag)flag=j+1;
break;//一旦遇到这段线段可以放在某一排就跳出循环
}
}
}
printf("%d\n",flag*10);
}
return 0;
}