蚂蚁问题
最近做了几个蚂蚁问题,还蛮有趣的。。。。。
蚂蚁问题第一弹:poj 1852 Ants:
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 12214 | Accepted: 5366 |
Description
Input
Output
Sample Input
2 10 3 2 6 7 214 7 11 12 7 13 176 23 191
Sample Output
4 8 38 207
题意:一根木棒上有很多蚂蚁,给出这些蚂蚁初始时离木棒左端的距离,当然这些蚂蚁一开始是向左爬还是向右爬是未知的。由于木棒很细,因此如果两只蚂蚁碰到了它们会各自掉头继续爬,问这些蚂蚁全都掉下去最少和最多需要多少时间。
题解:首先可以确定两只蚂蚁相撞之后速度大小不变,只是换了一个方向而已,而且我们要求的是时间大小,具体是哪一只没差。那么可以把每一只蚂蚁相撞的情况看成是穿过。那么这一只蚂蚁要走的路的长短取决于方向即:L(木棒长)-X(初始位置)或者 X。
#include <iostream> #include <cstdio> using namespace std; int main() { int T,L,n; cin>>T; while(T--) { int temp,cc,Min=-1e9,Max=-1e9; cin>>L>>n; for(int i=0;i<n;i++) { cin>>temp; cc=min(L-temp,temp); Min=max(cc,Min); cc=max(L-temp,temp); Max=max(cc,Max); } cout<<Min<<" "<<Max<<endl; } return 0; }
蚂蚁问题第二弹:UVA 10881 Piotr's Ants
一根长度为L厘米的木棍上有n只蚂蚁,每只蚂蚁要么往左爬要么往右爬,速度为1cm/s。当两只蚂蚁相遇时,二者同时掉头(掉头时间忽略不计)。给出每只蚂蚁的初始位置和朝向,计算T秒之后蚂蚁的位置。
输入第一行为数据组数。每组第一行为三个整数L,T,n(n≤10 000);以下n行描述一只蚂蚁的初始位置,其中,整数x为蚂蚁距左端的距离(单位:厘米),字母表示初始朝向(L向左,R向右)。
对于每组数据,输出n(Case #n:),按输入顺序输出每只蚂蚁的位置和朝向(Turning表示正在碰撞)。在T秒之前已经掉落的蚂蚁(正好爬到边缘不算)输出Fell off
样例输入:
2
10 1 4
1 R 5 R 3 L 10 R
10 2 3
4 R 5 L 8 R
样例输出:
Case #1:
2 Turning
6 R
2 Turning
Fell off
Case #2:
3 L
6 R
10 R
题意:同样是蚂蚁爬杆问题,不过这道题相比上一道题增加了一些难度,他会告诉你蚂蚁的初始爬行方向,要你求出T秒后蚂蚁的位置以及爬行方向
思路:首先我们可以知道,由于存在这么一个条件:两只蚂蚁如果碰头了那么它们就会反向掉头,又因为所有的蚂蚁速度都是相同的大小,那么除了那些掉下去的蚂蚁,所有的蚂蚁位置都是不变的,比如说1号蚂蚁在2号蚂蚁的左边,那么不论它们走多久,1号蚂蚁都不会走到2号蚂蚁的右边。因此我们可以对所有蚂蚁的位置进行一次排序,那么在行走前和行走后蚂蚁们的相对位置都是不变的,就可以解决掉判断是否是turnning这种情况了,然后就是和上道题一样的解法,可以把相撞的情况看成是穿过。。。。
#include <iostream> #include <algorithm> #include <cstdio> using namespace std; const int maxn=1e4+10; struct node { int id,p,d; bool operator < (const node &another) const { return p<another.p; } }a[maxn],c[maxn]; int idx[maxn]; int main() { int T,ca=1; cin>>T; while(T--) { int l,t,n; cin>>l>>t>>n; for(int i=0;i<n;i++) { char ch; scanf("%d %c",&a[i].p,&ch); switch(ch) { case 'R':a[i].d=1;break; case 'L':a[i].d=-1;break; } c[i].p=a[i].p; c[i].id=i; a[i].p+=t*a[i].d; if(a[i].p<0||a[i].p>l) a[i].d=0; } sort(c,c+n); sort(a,a+n); for(int i=0;i<n-1;i++) { if(a[i].p==a[i+1].p) a[i].d=a[i+1].d=2; } for(int i=0;i<n;i++) idx[c[i].id]=i; cout<<"Case #"<<ca++<<":"<<endl; for(int j=0;j<n;j++) { int i=idx[j]; switch(a[i].d) { case -1:cout<<a[i].p<<" "<<"L"<<endl;break; case 0:cout<<"Fell off"<<endl;break; case 1:cout<<a[i].p<<" "<<"R"<<endl;break; case 2:cout<<a[i].p<<" "<<"Turning"<<endl;break; } } puts(""); } return 0; }
蚂蚁问题第三弹:NYOJ 990
- 描述
长100厘米的细长直杆子上有n只蚂蚁。它们的头有的朝左,有的朝右。 每只蚂蚁都只能沿着杆子向前爬,速度是1厘米/秒。 当两只蚂蚁碰面时,它们会同时掉头往相反的方向爬行。 这些蚂蚁中,有1只蚂蚁感冒了。并且在和其它蚂蚁碰面时,会把感冒传染给碰到的蚂蚁。 请你计算,当所有蚂蚁都爬离杆子时,有多少只蚂蚁患上了感冒。
- 输入
第一行输入一个整数n (1 < n < 50), 表示蚂蚁的总数。
接着的一行是n个用空格分开的整数 Xi (-100 < Xi < 100), Xi的绝对值,表示蚂蚁离开杆子左边端点的距离。正值表示头朝右,负值表示头朝左,数据中不会出现0值,也不会出现两只蚂蚁占用同一位置。其中,第一个数据代表的蚂蚁感冒了。
- 输出
要求输出1个整数,表示最后感冒蚂蚁的数目。
- 样例输入
- 3
- 5 -2 8
- 5
- -10 8 -20 12 25
- 样例输出
- 1
- 3
- 思路:做这道题一定要注意,只有第一只蚂蚁的感冒具有传染性。可以把第一只蚂蚁看做一个中间感染源,那么可以确定这只蚂蚁的左边的往左远离它的蚂蚁以及右边的往右远离它的蚂蚁都是安全的,有危险的左边往右的以及右边往左的,而且由于蚂蚁的循环掉头,可以确定这些蚂蚁都会被感染。当然,如果这只感染源蚂蚁向左而他左边不存在左边向右的那么他就感染不到别的蚂蚁了
#include <iostream> #include <algorithm> #include <cmath> #include <cstdio> using namespace std; int sum1,sum2; void judge(int a1,int a2) { if((a2>0)&&(abs(a1)>abs(a2))) sum1++; if((a2<0)&&(abs(a1)<abs(a2))) sum2++; } int main() { int n; while(cin>>n) { int t,cc; cin>>t; sum1=0;sum2=0; for(int i=0;i<n-1;i++) { cin>>cc; judge(t,cc); } if(t<0&&sum1==0||t>0&&sum2==0) cout<<1<<endl; else cout<<sum1+sum2+1<<endl; } return 0; }