◆考试题目◆◇NOIP模拟赛◇robot(机器人)

来源:互联网 发布:手机系统克隆软件 编辑:程序博客网 时间:2024/06/04 18:16

◇NOIP模拟赛◇robot


Description
小麦最近发明了一个机器人,现在他把机器人拿到一个巨大的测试场地来测试。你可以想像这个测试场地是一个笛卡尔坐标系。现在机器人位于(0,0)处。给机器人一系列指令,机器人将可以根据指令来移动。指令分为四种{S,J,I,Z}。S表示往北移动一步,若当前机器人所在的坐标为(x,y),则机器人将移动到(x,y+1);J表示往南移动一步,若当前机器人所在的坐标为(x,y),则机器人将移动到(x,y-1);I表示往东移动一步,若当前机器人所在的坐标为(x,y),则机器人将移动到(x+1,y);Z表示往西移动一步,若当前机器人所在的坐标为(x,y),则机器人将移动到(x-1,y)。
在测试场地上有许多测距站,可以测出该点到机器人所在位置的曼哈顿距离。A点(x1,y1)和B点(x2,y2)的曼哈顿距离,即为|x1-x2|+|y1-y2|。
现在给出机器人的M条指令,机器人每走一步,测距站都会测一次距离。求每条指令后所有测距站测的的距离之和。

Input
给出整数N,M(1<=N<=100000,1<=M<=300000)。N表示测距站的个数,M表示指令条数。
接下来N行,每行给出两个整数,表示该测距站的x,y坐标。
再接下来一行,包含M个字符,表示M条命令。
Output
M行,每行包含一个整数,表示所有测距站测的的距离之和。

Sample Input

1 30 -10ISI

Sample Output

111213

题目解析
这道题主要是考察算法效率,如果直接暴力模拟的话是肯定超时的。(先把注意点说完吧)开long long信不信由你。(再说一下什么是曼哈顿距离吧)令A、B的曼哈顿距离为 F(A,B),在平面直角坐标系上,则 F(A,B)=|xAxB|+|yAyB|。由于每一次移动得到的值都与上一次移动得到的值有关联。
突然想水一篇博客
由于我们并不需要知道每一个点的确切位置,甚至不需要匹配每一个点的坐标!我们只需要知道对于机器人相对位置(上下左右)的点的数量就可以了——可以在输入时就预处理出来。由于我们不需要知道每一个点的确切坐标,也就是说我们只需要知道横坐标为x以及纵坐标为y的点有多少个就行了。我们可以把它们存在数组里(totx[i]表示横坐标为i的点的个数,toty[i]表示纵坐标为i的点的个数)。但是童鞋们是否发现坐标有负数?这个坑,也就是说不能用数组存。还好有C++,STL有一个神奇的容器——map < int > 。它的下标是一个任意的int变量,哪怕是负数!!!(可惜速度有点慢)现在所有问题都解决了。
现在来分析一下规律——我们不妨设机器人当前的总距离为 Sum 下一步行进的方向有 X 个点,行进方向的另一边有 Y 个点。我们很容易发现——移动后的机器人相对于上一位置,离它行进方向背面的点的距离都增加了1,而离它行进方向的点的距离都减少了1,那么现在的位置的总和 Sum+YX。注意要先移动机器人,更新 XY后再计算。


?代码?(不叫“样例程序”了)

/*Lucky_Glass*/#include<cstdio>#include<iostream>#include<map>#define fabs(a) (a>0? a:-a)using namespace std;int Num_Point,Num_Code,Up_X,Down_X,Left_X,Right_X;long long Sum;map<int,long> X,Y;char Code[300005];int main(){    scanf("%d%d",&Num_Point,&Num_Code);    for(int i=0,x,y;i<Num_Point;i++)    {        scanf("%d%d",&x,&y),X[x]++,Y[y]++;        if(y>0) Up_X++;if(y<0) Down_X++;if(x>0) Right_X++;if(x<0) Left_X++;        Sum+=fabs(x)+fabs(y);    }    cin>>Code;    int x=0,y=0;    for(int i=0;i<Num_Code;i++)    {        switch(Code[i])        {            case 'I':                 Left_X+=X[x];                Sum=Sum+Left_X-Right_X;                Right_X-=X[++x];                break;            case 'S':                 Down_X+=Y[y];                Sum=Sum+Down_X-Up_X;                Up_X-=Y[++y];                break;            case 'Z':                 Right_X+=X[x];                Sum=Sum+Right_X-Left_X;                Left_X-=X[--x];                break;            case 'J':                 Up_X+=Y[y];                Sum=Sum+Up_X-Down_X;                Down_X-=Y[--y];                break;        }        printf("%lld\n",Sum);    }    return 0;}

The End

Thanks for reading!

-Lucky_Glass


原创粉丝点击