【NOIP2013模拟11.4A组】游乐场

2024-05-29 03:08
文章标签 模拟 游乐场 noip2013 11.4

本文主要是介绍【NOIP2013模拟11.4A组】游乐场,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Description

今天是个好日子,小A和他的小伙伴们一起去逛游乐园。这时,游乐园中忽然出现了一个伪装的吸血鬼,小A和他的小伙伴们都惊呆了!小伙伴们马上跑向了游乐园的四面八方。当“吸血鬼”回家吃饭的时候,小A才发现他已经和他的小伙伴们走散了。小A是个路痴,所以他只好站在原地等小伙伴们回来。

我们可以将游乐园视为一个N行M列的矩形,最上面一行为第1行,最左边一列为第1列。每个小伙伴手里都有一张神奇的地图,地图中对应着游乐园的每行每列都有一个写着0-9中某个数字的路标。小A的K位小伙伴们每一秒都会依次进行以下行动:

  1. 读取他所在的位置上的路标X;

  2. 顺时针旋转90度X次;

  3. 如果他面对游乐园外,那就他会再转180度;

  4. 移动到他面对的位置。

小A的视力很糟糕。只有当所有的小伙伴都同时出现在他所在的位置时,他才能和他的小伙伴们团聚。小A等得很心急,所以他求助于你。请你告诉他,他和小伙伴们团聚所需要的时间。

Input

输入的第一行包括正整数N、M和K。

输入的第二行包括正整数X和Y,代表小A的位置。

输入的其他行将分别描述K个小伙伴:

·两个正整数Xi,Yi,代表第i个小伙伴开始时所在的位置。字符Ci,代表该小伙伴开始时面对的方向(U为上,R为右,D为下,L为左);

·由0-9(含)组成的N×M的地图,其中第x行第y列的数字表示该小伙伴地图上(x, y)的位置上的路标。

Output

唯一的一行输出小A和小伙伴们团聚所需要的时间。如果小A和他的小伙伴们永远不会团聚,请输出-1。

Sample Input

输入1:
3 3 1
2 2
1 1 R
010
000
000
输入2:
3 4 2
2 2
3 4 R
2327
6009
2112
3 2 R
1310
2101
1301
输入3:
4 4 3
4 3
1 1 U
1001
0240
3322
2327
1 3 L
9521
2390
3020
2421
2 2 D
3397
2013
1102
7302

Sample Output

输出1:
3
输出2:
8
输出3:
296

Data Constraint

对于30%的数据,如果小A和他的小伙伴们能够团聚,团聚的总秒数小于10^6;
对于70%的数据,3<=N, M<=40;
对于100%的数据,3<=N, M<=50,1<=K<=5如果小A和他的小伙伴们能够团聚,团聚的总秒数小于10^18。

Solution

首先对每个人进行模拟,会发现他会走成一个环。
因为有四个方向,所以到达目标点也会有最多四个状态。
对于每个这四个状态,记录从开头走到这里的时间ai,还有环的大小bi,如果状态不在环内,bi为0
只有5个人,4个状态,先枚举每个人选哪一个状态 54
那么就会得到一个方程
设时间为t,x为未知数
t=a1+b1x1
t=a2+b2x2
t=ai+bixi
这就是一个典型的中国剩余定理的方程,可以套用公式得出最优解t
但是因为我不懂那个中国剩余定理的公式,所以我用的是扩展欧几里得的解法
每次只算两个方程
如方程1、2:
a1+b1x1=a2+b2x2
b1x1b2x2=a2a1
然后就变成了 ax+by=c 的形式,解这个方程
然后将x或y代入原方程中,得到这两个方程的最优解t’
然后将这两个方程合并,变成
t=t+lcm(b1,b2)x
为什么能变成这样?
因为t’相当于第一个满足原方程的时间,而lcm就是两个都走完环回到原点的最短时间,意义与原方程相同

就这么化简到只剩一个方程,即可得出解
还有b=0或两个b相等的特殊情况,特判即可

Code

#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 60
#define ll long long
#define min(a,b) ((a)<(b)?(a):(b))
#define fo(i,a,b) for(ll i=a;i<=b;i++)
#define INF 100000000000000001ll
using namespace std;
ll n,m,k,x1,y1,a[N][N],b[6][4],c[6][4],d[6],bz[N][N][4],ans=INF;
void hzj(ll &x,ll &y,ll &z)
{(z+=a[x][y])%=4;if(x==1&&z==0) z=2;if(y==1&&z==3) z=1;if(x==n&&z==2) z=0;if(y==m&&z==1) z=3;if(z==0) x--;if(z==1) y++;if(z==2) x++;if(z==3) y--;
}
void exgcd(ll a,ll b,ll &x,ll &y)
{if(b==0){x=1,y=0;return;}exgcd(b,a%b,x,y);ll t=x;x=y;y=t-a/b*y;
}
ll gcd(ll a,ll b)
{return b==0?a:gcd(b,a%b);
}
ll getans(ll b1,ll a1,ll b2,ll a2)
{ll a=b1,b=-b2,c=a2-a1,x=0,y=0;if(b1==0&&b2==0){if(a2==a1) return a2;else return INF;}if(b1==0){if(b>c&&c%b==0) return max(a1,a2);else return INF;}if(b2==0){if(c>a&&c%a==0) return max(a1,a2);else return INF;}if(b1==b2){if(abs(a2-a1)%b1==0) return max(a1,a2);else return INF;}ll g=gcd(a,b);if(c%g!=0) return INF;exgcd(a,b,x,y);c/=g;x*=c;b=abs(b);b/=g;if(x<0) x=(b+x%b);x%=b;return a1+b1*x;
}
void pd()
{ll q[6],w[6];fo(i,1,k) q[i]=b[i][d[i]],w[i]=c[i][d[i]];if(k==1){ans=min(ans,q[1]);return;}fo(i,1,k-1){q[i+1]=getans(w[i],q[i],w[i+1],q[i+1]);if(gcd(w[i],w[i+1])==0) w[i+1]=0;else w[i+1]=w[i]*w[i+1]/gcd(w[i],w[i+1]);}ans=min(ans,q[k]);
}
void dg(ll x)
{if(x>k) {pd();return;}fo(i,0,3) if(b[x][i]!=0) d[x]=i,dg(x+1);
}
int main()
{freopen("park.in","r",stdin);freopen("park.out","w",stdout);scanf("%lld%lld%lld",&n,&m,&k); scanf("%lld%lld\n",&x1,&y1);fo(l,1,k){char ch;ll x,y,z,lh,jy;scanf("%lld %lld %c\n",&x,&y,&ch);if(ch=='U') z=0;if(ch=='R') z=1;if(ch=='D') z=2;if(ch=='L') z=3;fo(i,1,n){fo(j,1,m) a[i][j]=getchar()-48;scanf("\n");}memset(bz,0,sizeof(bz));fo(i,0,3) b[l][i]=0;fo(i,1,2147483647)if(!bz[x][y][z]){bz[x][y][z]=i;if(x==x1&&y==y1) b[l][z]=i;hzj(x,y,z);}else{lh=i-bz[x][y][z];jy=bz[x][y][z];break;}fo(i,0,3) if(b[l][i]>=jy) c[l][i]=lh;else c[l][i]=0;}dg(1);if(ans==INF) ans=-1;printf("%lld",ans);
}

这篇关于【NOIP2013模拟11.4A组】游乐场的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1012474

相关文章

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

usaco 1.2 Transformations(模拟)

我的做法就是一个一个情况枚举出来 注意计算公式: ( 变换后的矩阵记为C) 顺时针旋转90°:C[i] [j]=A[n-j-1] [i] (旋转180°和270° 可以多转几个九十度来推) 对称:C[i] [n-j-1]=A[i] [j] 代码有点长 。。。 /*ID: who jayLANG: C++TASK: transform*/#include<

hdu4431麻将模拟

给13张牌。问增加哪些牌可以胡牌。 胡牌有以下几种情况: 1、一个对子 + 4组 3个相同的牌或者顺子。 2、7个不同的对子。 3、13幺 贪心的思想: 对于某张牌>=3个,先减去3个相同,再组合顺子。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOExcepti

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

【算法专场】模拟(下)

目录 前言 38. 外观数列 算法分析 算法思路 算法代码 1419. 数青蛙 算法分析 算法思路 算法代码  2671. 频率跟踪器 算法分析 算法思路 算法代码 前言 在前面我们已经讲解了什么是模拟算法,这篇主要是讲解在leetcode上遇到的一些模拟题目~ 38. 外观数列 算法分析 这道题其实就是要将连续且相同的字符替换成字符重复的次数+

模拟实现vector中的常见接口

insert void insert(iterator pos, const T& x){if (_finish == _endofstorage){int n = pos - _start;size_t newcapacity = capacity() == 0 ? 2 : capacity() * 2;reserve(newcapacity);pos = _start + n;//防止迭代

PHP实现二叉树遍历(非递归方式,栈模拟实现)

二叉树定义是这样的:一棵非空的二叉树由根结点及左、右子树这三个基本部分组成,根据节点的访问位置不同有三种遍历方式: ① NLR:前序遍历(PreorderTraversal亦称(先序遍历)) ——访问结点的操作发生在遍历其左右子树之前。 ② LNR:中序遍历(InorderTraversal) ——访问结点的操作发生在遍历其左右子树之中(间)。 ③ LRN:后序遍历(PostorderT

1 模拟——67. 二进制求和

1 模拟 67. 二进制求和 给你两个二进制字符串 a 和 b ,以二进制字符串的形式返回它们的和。 示例 1:输入:a = "11", b = "1"输出:"100"示例 2:输入:a = "1010", b = "1011"输出:"10101" 算法设计 可以从低位到高位(从后向前)计算,用一个变量carry记录进位,如果有字符没处理完或者有进位,则循环处理。两个字符串对