原题:http://www.usaco.org/index.php?page=viewproblem2&cpid=205#
Problem 1: Meet and Greet [Brian Dean, 2012]As is commonly known, cows are very socially polite creatures: any time twocows meet after being apart, they greet each-other with a friendly "moo".Bessie the cow and her friend, Elsie, are walking around on a longpath on Farmer John's farm. For all practical purposes, we can thinkof this path as a one-dimensional number line. Bessie and Elsie bothstart at the origin, and they both then begin walking around atidentical speeds for some amount of time. Given a description of themovements taken by each cow, please determine the number of "moos"exchanged. Bessie and Elsie can stop moving at different points in time, andneither cow will travel for more than 1,000,000 units of time.
PROBLEM NAME: greetings
INPUT FORMAT:
SAMPLE INPUT (file greetings.in):
INPUT DETAILS:
OUTPUT FORMAT:
SAMPLE OUTPUT (file greetings.out):
UTPUT DETAILS:
题意:有两头牛Bessie和Elsie,给出两个正整数B和E,分别代表Bessie和Elsie的移动情况个数,然后每一行给出一个正整数dt和一个方向dir,代表牛向左或者向右走了dt个单位时间。牛移动的速度是一样的,自从它们从同一个起点分离后一见面就会发出“moo”的声音,问它们总共发了几次声音。
算法思路:对每一头牛的某个时刻的移动情况进行记录,然后按时间从小到大排序。然后遍历比较。
Solution Notes (Jonathan Paulson): This is a simulation problem, and the constraint that the cows only travel for 10^6 seconds makes it pretty straightforward. You can just write down for each cow where it is at each second as you read the input, and then count the number of times T when their positions at T were different but their positions at T+1 were the same.
The problem is still efficiently solvable if the times are much larger (say, up to 10^12) but the number of instructions is still small (say, 100,000). Then the solution is a version of coordinate compression (which also makes an appearance in "crazy fences"); the only "interesting times" are when a cows speed changes, and there are at most 200,000 of these (each instruction causes an increase and then decrease in speed; actually, since the start of one instruction and the beginning of another overlap, the real number is more like 100,000 but this isn't important). To simplify implementation of this idea, it is useful to keep track of Bessie's movement relative to Elsie, instead of their absolute positions. Then a moo occurs when Bessie passes 0. Now that time is divided up into ~100,000 intervals of constant speed, it is easy to compute the change in position due to each time interval, and keep track of the number of times Bessie passes 0.
实现代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <climits>
using namespace std;
const int INF=0x3f3f3f3f;
#define Bessie 0
#define Elsie 1
struct KeyPoint
{
int t,cow,newdir;
KeyPoint(int t,int cow,int newdir):t(t),cow(cow),newdir(newdir){}
bool operator < (KeyPoint const& x) const
{
return t<x.t;
}
};
vector<KeyPoint> keyPoints;
//读取每一头牛的一系列移动
int read_keyPoints(int n,int cow)
{
int t=0;
int initdir;
for(int i=0;i<n;i++)
{
int dt;
char c;
int dir;
scanf("%d %c",&dt,&c);
dir=(c=='L' ? -1:1);
if(t==0)
{
initdir=dir;
}
else
{
keyPoints.push_back(KeyPoint(t,cow,dir));
}
//记录时刻
t+=dt;
}
keyPoints.push_back(KeyPoint(t,cow,0));
return initdir;
}
int main()
{
int B,E;
keyPoints.clear();
freopen("greetings.in","r",stdin);
freopen("greetings.out","w",stdout);
scanf("%d%d",&B,&E);
//初始化每一头牛一开始移动方向
int dir0=read_keyPoints(B,Bessie);
int dir1=read_keyPoints(E,Elsie);
//对时刻进行排序
sort(keyPoints.begin(),keyPoints.end());
//初始化时刻,每头牛的位置
int t=0;
int x0=0;
int x1=0;
//牛的“moos"次数
int moos=0;
for(int i=0;i<keyPoints.size();i++)
{
//时间来到new_t时刻
int new_t=keyPoints[i].t;
//牛来到的新位置
int new_x0=x0+(new_t-t)*dir0;
int new_x1=x1+(new_t-t)*dir1;
//判断两牛是否在(t,new_t]发出”moos"叫声。
//如果两牛发出声音,它们上一次一定没有发“moos",然后2种情况:一种在new_t见面,另一种在(t,new_t)见面,异或处理表示二者只有一个成立
if(x0!=x1&&((new_x0==new_x1)||((x0<x1)^(new_x0<new_x1))))moos++;
//更新时刻和方向
t=new_t;
x0=new_x0,
x1=new_x1;
if(keyPoints[i].cow==Bessie)dir0=keyPoints[i].newdir;
else dir1=keyPoints[i].newdir;
}
printf("%d\n",moos);
return 0;
}