您的位置:首页 > 其它

【经典问题】蚂蚁爬杆问题

2013-05-20 15:35 357 查看
( 转载请注明出处.......... http://blog.csdn.net/jiangzh7 ................. By Jiangzh )

先说说是什么问题:

告诉你有一个长为L(L<=10000)的木杆,上面有N(N<=1000)个蚂蚁,他们一开始的朝向随机,他们会以一定的速度一直向当前方向走,直到两只蚂蚁相遇,他们会立即掉头(即往相反方向走),注意,掉头不耗时间。问多久后蚂蚁全部掉下木杆,所有蚂蚁走的总路程是多少?

为了方便,我们假设速度为 1 ( 即每一秒走一步 )

好,问题到此结束,我们先来模拟一下,比如下面一个图

0___1___2___3___4___5
____->______<-

上面两个箭头表示两只蚂蚁的朝向,很明显他们会在2相遇后立即掉头,然后左边的蚂蚁再走两步掉下,总共三步,而右边那一只还需要走三步,总共四步,那么 4s 后所有蚂蚁都会掉下木杆,总路程为7步

再如下面

0___1___2___3___4___5
____<-______->

两个蚂蚁不会相遇,2s后所有蚂蚁掉下,总路程3步

那么这一类问题怎么解决呢?枚举?似乎。。。。。。。

我们先来思考一个问题,如果不掉头而是擦肩而过会怎么做呢?只需要把每个蚂蚁走的路程加起来就是总路程,最长的哪一个 路程 / 速度 就是总时间

至于求每个蚂蚁走的路程就不说了,设位置为pos,如果向左,那么time=pos,否则time=L-pos

想上面如果不考虑掉头是不是很简单?

这时候其实方法已经出来了,我们关心的只是最终结果,而至于他们掉下去的顺序这些是不关心的,那么当他们每次相遇的时候,我们可以看作他们交换身份然后继续向前走,而不是掉头!这样就成了上面说的那种非常简单的情况了,O(N)就可以解决

CDOJ1025 就是这样一道裸题

C++ AC Code

/*http://blog.csdn.net/jiangzh7
By Jiangzh*/
#include<cstdio>
int n,L,v;
int main()
{
freopen("1025.in","r",stdin);
freopen("1025.out","w",stdout);
while(scanf("%d%d%d",&n,&L,&v)==3&&n&&L&&v)
{
int sum=0,max=0;
for(int i=1;i<=n;i++)
{
int pos;
char s[10];scanf("%d%s%s",&pos,s,s);
if(pos==0 && s[0]=='0') break;
int leng;
if(s[0]=='E') leng=L-pos;
else leng=pos;
if(leng>max) max=leng;
sum+=leng;
}
printf("%.2lf %d.00\n",(double)max/v,sum);
}
return 0;
}


然后 CDOJ1365 就上了一个阶梯了

他求的不是最终结果,而是求中间的过程,也就是按先后顺序输出蚂蚁掉落的时间以及他是哪一只蚂蚁(即名字)

还能用上面的方法来做吗?我相信,如果只是输出掉落的时间,按照上面的方法可以做出,只需要把时间排一次序,然后输出即可

但是我们还需要输出蚂蚁的信息,也就是我们不能无视他们是否掉头了

在这之前我们应该明确一个东西:最早掉下去的一定是最左或者最右的蚂蚁

我们已经知道了每次掉落的时间,如果能知道方向的话,即如果向左,那么一定是最左的蚂蚁落下,反之最右的蚂蚁落下,那么就可以解决这个问题

可以开一个结构体,记录时间和方向,然后按照时间排序,解决第一问,然后再按照每个蚂蚁的坐标排序,根据时间排序后的方向可以确定蚂蚁落下的顺序

其实我们也不用开结构体,用正负表示方向,排序按照绝对值排序即可

差不多了,代码出炉

C++ AC Code

/*http://blog.csdn.net/jiangzh7
By Jiangzh*/
#include<cstdio>
#include<cstdlib>
#include<algorithm>
const int N=100+10;
int n,L;
struct node{char name[20];int pos;}a
;
int time
;

bool cmp_abs(int a,int b) { return abs(a)<abs(b); }//按绝对值排序
bool cmp_node(node a,node b) { return a.pos<b.pos; }//按坐标排序

void work()
{
scanf("%d%d",&n,&L);
for(int i=1;i<=n;i++)
{
scanf("%s%d",a[i].name,&a[i].pos);
char op[10]; scanf("%s",op);
if(op[0]=='L') time[i]=a[i].pos;
else time[i]=-(L-a[i].pos);//正负表示方向
}
std::sort(time+1,time+1+n,cmp_abs);
std::sort(a+1,a+1+n,cmp_node);
int head=1,tail=n;
for(int i=1;i<=n;i++)
{//根据方向,最左或最右的蚂蚁会掉下
if(time[i]>0)
{
printf("%d %s\n",time[i],a[head].name);
head++;
}
else{
printf("%d %s\n",-time[i],a[tail].name);
tail--;
}
}
}

int main()
{
freopen("1365.in","r",stdin);
freopen("1365.out","w",stdout);
int T; scanf("%d",&T);
for(int cas=1;cas<=T;cas++)
{
printf("Case #%d:\n",cas);
work();
}
return 0;
}


( 转载请注明出处.......... http://blog.csdn.net/jiangzh7 ................. By Jiangzh )
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: