3298: [USACO 2011Open]cow checkers
3298: [USACO 2011Open]cow checkers
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 65 Solved: 26
Description
一天,Besssie准备和FJ挑战奶牛跳棋游戏。这个游戏上在一个M*N(1<=M<=1,000,000;1<=N<=1,000,000)的棋盘上, 这个棋盘上在(x,y)(0<=x棋盘的左下角是(0,0)坐标,棋盘的右上角是坐标(M-1,N-1)。 Bessie每次都是第一个移动棋子,然后Bessie与Fj轮流移动。每一轮可以做以下三种中的一种操作: 1)在同一行,将棋子从当前位置向左移动任意格; 2)在同一列,将棋子从当前位置向下移动任意格; 3)将棋子从当前位置向下移动k格再向左移动k格(k为正整数,且要满足移动后的棋子仍然在棋盘上) 第一个不能在棋盘上移动的人比赛算输(因为棋子处在(0,0)点)。 共有T个回合(1<=T<=1,000),每次给出一个新起始点的坐标(x,y),确定是谁赢。
Input
第1行:两个用空格隔开的整数M和N; 第2行:一个整数T; 第3到第T+2行:两个用空格隔开的整数x和y.
Output
第1到T行:包含“Farmer John”或者是“Bessie”,表示谁赢了这轮游戏。
Sample Input
3 3 1 1 1
Sample Output
Bessie
HINT
Source
题解:实际上,一上来此题目不难想到可以通过DP(或者记忆化搜索也行)来搞,但这样问题来了——N,M<=1000000,显然会爆。。。
于是只好来另辟蹊径——(明确两个概念: 死点:表示当某一方在还未走这一步之前如果落到了这个位置将必死无疑的点 活点:正好相反)
1.题目中说从(N-1,M-1)走到(0,0),既然这样,我们何不看作从(0,0)走到(N-1,M-1)呢?
2.题目中说可以横向走,可以纵向走,可以斜向走,这不就意味着只要某一点被认定为死点,则这一个点横向、纵向、斜向上的其他点都是活点么(很明显如果某人走到了死点横向、斜向、纵向上的其他点上的话,他就可以把对手一步送到死点上,结束战斗。。。)
3.由2可知,所有的死点必然不在同一行,同一列,同一对角线上,也就是说对于某一x或者y坐标而言,其上死点的坐标是唯一的
4.所以综上所述,可以通过简单的O(N)预处理来实现求出每一个x坐标上的死点位置,然后接下来对于每个询问只要O(1)判断是否相同即可
于是,我们来开始找规律:
如上图,黑色的斜线表示对称轴,蓝箭头连着的是对称的,而红色箭头均为与对称轴平行的线,很明显所有下半边的点所在的线间隔都是1单位,这样一来规律就很分明了——对于当前的x坐标,要么已经通过之前的某点对称得到了结果,如果没得到的话,那就根据上一个同侧的点从斜线方向挪一格,然后对称一下得出上半边那个点,实现快速求解
1 /**************************************************************
2 Problem: 3298
3 User: HansBug
4 Language: Pascal
5 Result: Accepted
6 Time:72 ms
7 Memory:4132 kb
8 ****************************************************************/
9
10 var
11 i,j,k,l,m,n:longint;
12 a:array[0..1000005] of longint;
13 function max(x,y:longint):longint;
14 begin if x>y then max:=x else max:=y; end;
15 begin
16 fillchar(a,sizeof(a),-1);
17 a[0]:=0;l:=0; readln(n,m);
18 for i:=1 to max(m,n) do
19 begin if a[i]>-1 then continue;
20 inc(l);a[i]:=i+l;if (i+l)<=1000005 then a[i+l]:=i; end;
21 readln(n);
22 for i:=1 to n do
23 begin
24 readln(j,k);
25 if k>j then begin l:=k;k:=j;j:=l end;
26 if a[j]<>k then writeln('Bessie') else writeln('Farmer John');
27 end;
28 end.
- 【Spring实战】—— 2 构造注入
- 共享单车运维“朋友圈”越来越宽,乱停乱放现象有望改善吗?
- 【Spring实战】—— 15 Spring JDBC模板使用
- 前端开发总览
- 【Spring实战】—— 16 基于JDBC持久化的事务管理
- 【Spring实战】—— 4 Spring中bean的init和destroy方法讲解
- 基于AngularJS的过滤与排序
- 【Spring实战】—— 5 设值注入
- 科学家预测:未来100万年人类将变成半机械人类
- 【Spring实战】—— 8 自动装配
- 【Spring实战】—— 7 复杂集合类型的注入
- 【Spring实战】—— 6 内部Bean
- 几款可替代Dreamweaver的HTML5开发工具
- Linux下的Telnet设置方法介绍
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 浙大版《C语言程序设计(第3版)》题目集 练习2-9 整数四则运算
- 浙大版《C语言程序设计(第3版)》题目集 练习2-10 计算分段函数[1]
- 浙大版《C语言程序设计(第3版)》题目集 练习2-11 计算分段函数[2]
- SAP Spartacus产品页面的normalizer
- Nodejs中使用net-snmp库读取智慧站房的温湿度、空调等实时数据
- 生气!面试官你过来,我给你手写一个Spring Aop实现!
- 浙大版《C语言程序设计(第3版)》题目集 练习2-12 输出华氏-摄氏温度转换表
- Linux下文本处理“三剑客”
- Thread和goroutine两种方式实现共享变量按序输出
- 浙大版《C语言程序设计(第3版)》题目集 练习2-13 求N分之一序列前N项和
- 浙大版《C语言程序设计(第3版)》题目集 练习2-14 求奇数分之一序列前N项和
- dotnet 双缓存数据结构设计 下载库的文件写入缓存框架
- 浙大版《C语言程序设计(第3版)》题目集 练习2-15 求简单交错序列前N项和
- 浙大版《C语言程序设计(第3版)》题目集 练习2-17 生成3的乘方表
- WPF 漂亮的现代化控件 新 ModernWPF 界面库