scu-4445
Right turn
frog is trapped in a maze. The maze is infinitely large and divided into grids. It also consists of nn obstacles, where the ii -th obstacle lies in grid (xi,yi)(xi,yi) .
frog is initially in grid (0,0)(0,0) , heading grid (1,0)(1,0) . She moves according to The Law of Right Turn: she keeps moving forward, and turns right encountering a obstacle.
The maze is so large that frog has no chance to escape. Help her find out the number of turns she will make.
Input
The input consists of multiple tests. For each test:
The first line contains 11 integer nn (0≤n≤1030≤n≤103 ). Each of the following nn lines contains 22 integers xi,yixi,yi . (|xi|,|yi|≤109,(xi,yi)≠(0,0)|xi|,|yi|≤109,(xi,yi)≠(0,0) , all (xi,yi)(xi,yi) are distinct)
Output
For each test, write 11 integer which denotes the number of turns, or ``-1'' if she makes infinite turns.
Sample Input
2
1 0
0 -1
1
0 1
4
1 0
0 1
0 -1
-1 0
Sample Output
2
0
-1
题意:青蛙在迷宫里面一直向前走,如果遇到障碍,就原地向右转,然后继续向前走。能走出迷宫,输出转向次数。
走不出去,输出-1。
这题前前后后花了我有近5个小时,琢磨出三种方法。
第一种,最笨的,模拟青蛙的一步一步走。
第二种,用for循环找障碍点。
第三种,根据障碍点来确定青蛙的位置。
三种方法的代码我都敲了。
第一种方法不出意料的TLE。
第二种竟然是MLE(第一次遇到这情况,在此纪念下)。
(第二种方法有位学长ac了,感兴趣的同学可以移步http://blog.csdn.net/a1dark/article/details/46583929)
第三种自己动了些脑筋而且一次过了,略微得意,结果前段时间翻博客发现早已经有学长用过这方法了 T T。
(第三种方法学长的博客:http://blog.csdn.net/qq_31759205/article/details/52299244)
我还是太年轻。
讲下第三种方法:
脑补一个二维坐标轴,青蛙在(0,0)点。
如果遇到障碍,则青蛙必定会走到障碍的前一个点。因此只需要操作并记录相应的障碍点就行了。
因为总共就四个方向,所以当一个障碍点被记录四次以上,则是陷入死循环。
附代码:
#include <cstdio>
#include<cstring>
#include<algorithm>
#define Maxx 3333
using namespace std;
struct ak
{
int x; //横坐标
int y; //纵坐标
int f; //在nu中用作记录碰到此点的次数 在nux和nuy中记录坐标在nu中的位置
}nu[Maxx],nux[Maxx],nuy[Maxx];
bool cmpx(ak a,ak b) //对nux进行x(横坐标)的从小到大排序
{
if(a.x<b.x) return 1;
return 0;
}
bool cmpy(ak a,ak b) //对nuy进行y(纵坐标)的从小到大排序
{
if(a.y<b.y) return 1;
return 0;
}
int main(void)
{
int fx,fy,flag=0; //(fx,fy)为模拟青蛙的坐标
int d; //d用来记录方向(direction),1,2,3,4分别是坐标的右,下,左,上
//flag用于记录青蛙走迷宫的三种情况 0:遇到障碍 1:死循环 2:走出迷宫
int t; //t(turn)记录青蛙旋转的次数
int i,l;
int n;
while(~scanf("%d",&n))
{
fx=0;fy=0;d=1;flag=0;t=0; for( l=0;l<n;l++)
{
scanf("%d %d",&nu[l].x,&nu[l].y);
nux[l].x=nu[l].x;nux[l].y=nu[l].y;
nuy[l].x=nu[l].x;nuy[l].y=nu[l].y;
nux[l].f=l; nuy[l].f=l;
}
sort(nux,nux+l,cmpx); //对nux进行x(横坐标)的从小到大排序
sort(nuy,nuy+l,cmpy); //对nuy进行y(纵坐标)的从小到大排序
while(1) //死循环 flag!=0时跳出
{
if(d==1) //四个方向
{
for( i=0;i<l;i++)
{
if(nu[nux[i].f].f>4) //如果在一个点前停止四次以上,则说明陷入死循环
{
flag=1;
break;
}
if(nux[i].y==fy&&nux[i].x>fx) //如果碰到障碍,转向
{
fx=nux[i].x-1;
nu[nux[i].f].f++;
t++;
d++;
break;
}
}
if(i>=l||i<0)
flag=2; }
if(d==2) //四个方向 同上
{
for( i=l-1;i>=0;i--)
{
if(nu[nuy[i].f].f>4)
{
flag=1;
break;
}
if(nuy[i].x==fx&&nuy[i].y<fy)
{
fy=nuy[i].y+1;
nu[nuy[i].f].f++;
t++;
d++;
break;
}
}
if(i>=l||i<0)
flag=2;
}
if(d==3) //四个方向 同上
{
for( i=l-1;i>=0;i--)
{
if(nu[nux[i].f].f>4)
{
flag=1;
break;
}
if(nux[i].y==fy&&nux[i].x<fx)
{
fx=nux[i].x+1;
nu[nux[i].f].f++;
t++;
d++;
break;
}
}
if(i>=l||i<0)
flag=2;
}
if(d==4) //四个方向 同上
{
for( i=0;i<l;i++)
{
if(nu[nuy[i].f].f>4)
{
flag=1;
break;
}
if(nuy[i].x==fx&&nuy[i].y>fy)
{
fy=nuy[i].y-1;
nu[nuy[i].f].f++;
t++;
d=1;
break;
}
}
if(i>=l||i<0)
flag=2;
}
if(flag!=0)
break;
} if(flag==1)
printf("-1\n");
else
printf("%d\n",t);
for( i=0;i<l;i++) //初始化
{
nu[i].f=0;nu[i].x=0;nu[i].y=0;
nux[i].f=0;nux[i].x=0;nuy[i].y=0;
nuy[i].f=0;nuy[i].y=0;nux[i].x=0;
}
}
return 0;
}
前段时间又遇到了这道题,做起来也顺手许多,附代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int inf = 0x3f3f3f3f;
const int M = 1111;
struct nod{
int x;
int y;
}nd[M];
int book[M];
int main(){
int n;
while(~scanf("%d",&n)){
memset(book,0,sizeof(book));
for(int i=0;i<n;i++){
scanf("%d %d",&nd[i].x,&nd[i].y);
}
int d=1,fx=0,fy=0,maxx=-inf,minn=inf,f=0,cnt=0,end=0,mi;
while(1){
maxx=-inf,minn=inf,f=0;
if(d==1){
for(int i=0;i<n;i++){
if(nd[i].y==fy&&nd[i].x>fx&&nd[i].x<minn){
minn=nd[i].x; f=1; mi=i;
}
}
if(f){
fx=minn-1; d=2;
book[mi]++;
cnt++;
if(book[mi]>4) {
end=1; break;
}
}
else break;
}
else if(d==2){
for(int i=0;i<n;i++){
if(nd[i].x==fx&&nd[i].y<fy&&nd[i].y>maxx){
maxx=nd[i].y;f=1; mi=i;
} }
if(f){
fy=maxx+1; d=3;
book[mi]++;
cnt++;
if(book[mi]>4) {
end=1; break;
}
}
else break;
}
else if(d==3){
for(int i=0;i<n;i++){
if(nd[i].y==fy&&nd[i].x<fx&&nd[i].x>maxx){
maxx=nd[i].x;f=1; mi=i;
}
}
if(f){
fx=maxx+1; d=4;
book[mi]++;
cnt++;
if(book[mi]>4) {
end=1; break;
}
}
else break;
}
else if(d==4){
for(int i=0;i<n;i++){
if(nd[i].x==fx&&nd[i].y>fy&&nd[i].y<minn){
minn=nd[i].y; f=1; mi=i;
}
}
if(f){
fy=minn-1; d=1;
book[mi]++;
cnt++;
if(book[mi]>4) {
end=1; break;
}
}
else break;
}
}
if(end==1) printf("-1\n");
else printf("%d\n",cnt);
}
return 0;
}
scu-4445的更多相关文章
- 模拟+贪心 SCU 4445 Right turn
题目传送门 /* 题意:从原点出发,四个方向,碰到一个点向右转,问多少次才能走出,若不能输出-1 模拟:碰到的点横坐标相等或纵坐标相等,然而要先满足碰到点最近, 当没有转向或走到之前走过的点结束循环. ...
- SCU 4445 Right turn(dfs)题解
思路:离散化之后,直接模拟就行,标记vis开三维 代码: #include<iostream> #include<algorithm> #include<cstdio&g ...
- SCU 4445 Right turn
模拟. 每次找一下即将要遇到的那个点,这个数据范围可以暴力找,自己的写的时候二分了一下.如果步数大于$4*n$一定是$-1$. #include<bits/stdc++.h> using ...
- ACM:SCU 4437 Carries - 水题
SCU 4437 Carries Time Limit:0MS Memory Limit:0KB 64bit IO Format:%lld & %llu Practice ...
- ACM: SCU 4438 Censor - KMP
SCU 4438 Censor Time Limit:0MS Memory Limit:0KB 64bit IO Format:%lld & %llu Practice D ...
- ACM: SCU 4440 Rectangle - 暴力
SCU 4440 Rectangle Time Limit:0MS Memory Limit:0KB 64bit IO Format:%lld & %llu Practic ...
- SCU 4424(求子集排列数)
A - A Time Limit:0MS Memory Limit:0KB 64bit IO Format:%lld & %llu Submit Status Practice ...
- SCU 2941 I NEED A OFFER!(01背包变形)
I NEED A OFFER! 64bit IO Format: %lld & %llu Submit Status Description Description Speakless ...
- SCU 4440 分类: ACM 2015-06-20 23:58 16人阅读 评论(0) 收藏
SCU - 4440 Rectangle Time Limit: Unknown Memory Limit: Unknown 64bit IO Format: %lld & %llu ...
- scu 4436: Easy Math 水题
4436: Easy Math Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.scu.edu.cn/soj/problem.actio ...
随机推荐
- [Usaco2009 Feb]Revamping Trails 道路升级
题目描述 每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M<=50,000)条双向泥土道路,编号为1..M. 道路i连接牛棚P1_i和P2_i (1 < ...
- TCP三次握手Linux源码解析
TCP是面向连接的协议.面向连接的传输层协议在原点和重点之间建立了一条虚拟路径,同属于一个报文的所有报文段都沿着这条虚拟路径发送,为整个报文使用一条虚拟路径能够更容易地实施确认过程以及对损伤或者丢失报 ...
- 消息队列之rabbitmq学习使用
消息队列之rabbitmq学习使用 1.RabbitMQ简介 1.1.什么是RabbitMQ? RabbitMQ是一个开源的消息代理和队列服务器,用来通过普通协议在完全不同的应用之间共享数据,Rabb ...
- Spring基于注解开发的注解使用之AOP(部分源代码分析)
AOP底层实现动态代理 1.导入spring-aop包依赖 <!--aopV1--> <dependency> <groupId>org.springframewo ...
- 使用注解的形式对token进行验证
@[TOC](使用注解的形式对token进行验证)# 前言现在很多系统都是都用上了springboot.springcloud,系统也偏向分布式部署.管理,最早的用户令牌方案:session.cook ...
- jvm源码解析java对象头
认真学习过java的同学应该都知道,java对象由三个部分组成:对象头,实例数据,对齐填充,这三大部分扛起了java的大旗对象,实例数据其实就是我们对象中的数据,对齐填充是由于为了规则分配内存空间,j ...
- Windows Server 2012 R2 英文版汉化安装中文语言包教程更改为中文版
是这样的,一台海外的windows机器默认是英文版的,但是特别费劲用起来,就更改为中文版,因为海外的供应商并不提供中文版镜像. 1.首先打开控制面板,找到add language,拉到底就是有中文,很 ...
- 在VMware15安装Ubuntu 16.04
安装环境: VMware15 VMware15官网地址:https://my.vmware.com/cn/web/vmware/info/slug/desktop_end_user_computing ...
- 常用shell命令及其用法
ls(lsit) 1.作用:列出文件列表 2.用法:ls [-a|-A--] [filename|directory] ls ls -a:查看隐藏文件 ls -l:查看文件详细信息 ...
- JavaWeb——JSP内置对象application,JSP属性范围
application application语法 application对象 JSP属性范围 范围的分类 page request session application pagecontext延伸 ...