#10259. 「2021CSP普及组模拟-计蒜客7月」T1:控枪 题解

【谨遵题解之意——肆】
鎏金神烟出品
题目部分
(注:题目皆来自tywzoj.top,如有侵权,请联系删除!)

题目描述

在枪战类游戏里每一把枪在开枪时都会有后坐力,这一后坐力会使玩家的枪不由自主地随机移动,我们称之为轨迹偏移。
这类游戏里为了模拟真实情况,一把枪有一个弹匣,弹匣中装有n发子弹;每射出n发子弹,玩家会换上下一个弹匣。
在游戏中,为了程序实现方便,同一把枪的后坐力导致的轨迹偏移往往是固定的,并且这一轨迹偏移序列的周期为弹匣的容量。因此,我们可以记住这把枪的轨迹偏移,然后用一个相反的鼠标移动抵消这一偏移,这样就实现了「控枪」。
于是,要达到枪枪必中,只需要令每一次移动鼠标追踪目标时的位移向量等于敌人的位移向量加上上一枪的轨迹偏移向量的相反向量。

输入格式
首先是一行两个正整数 n n n, m m m,分别表示枪的轨迹偏移周期和需要开的枪数。之后是 n − 1 n-1 n1行,每行两个整数,分别表示第 i i i发子弹射出后的轨迹偏移。由于第 n n n次射击后要换弹匣,所以不考虑第 n n n次射击产生的轨迹偏移,因此显然每个弹匣的第1枪没有轨迹偏移。之后是 m m m行,每行两个整数,分别表示每一次开枪时敌人所在的位置。
输出格式
输出 m行,每行两个整数 a n s x , a n s y ansx,ansy ansx,ansy ,表示开第 i i i枪所需的鼠标位移向量。我们认为开第一枪之前鼠标位于 ( 0 , 0 ) . (0,0). (0,0).

i n p u t 1 input1 input1

3 3
3 3
-3 -3
1 1
0 0
1 1

o u t p u t 1 output1 output1

1 1
-4 -4
4 4

i n p u t 2 input2 input2

4 6
2 2
7 8
9 9
-1 -5
1 1
-2 -2
-4 -4
3 3
2 2

o u t p u t output output

-1 -5
0 4
-10 -11
-11 -11
7 7
-3 -3

大家看完题,先试着做亿做( b u s h i bushi bushi),再来看题解吧!
题解部分

先读题 试着理解一下那些反人类语言,前面基本是废话,最后一段说:只需要令每一次移动鼠标追踪目标时的位移向量等于敌人的位移向量加上上一枪的轨迹偏移向量的相反向量,很多人看了题都会一脸蒙圈,这个时候不要怕,结合样例看更好哦。
根据题中可知,先要定义ansx与ansy来记录要移动的数量,方便输出。
接着定义数组来存储固定的开枪轨迹偏移和敌人的移动

int ax[1000005],ay[1000005],bx[1000005],by[1000005];//定义开枪的轨迹偏移和敌人的移动

由题可知,要输入 n − 1 n-1 n1行,这是因为第一发子弹可以看做没有偏移值

	ax[1]=0;//第一发x偏移值为0
	ay[1]=0;//第一发y偏移值为0
for(int i=2;i<=n;i++){
		scanf("%d%d",&ax[i],&ay[i]);//从第二发到第n发进行输入
	}

这里要注意,本题的测试数据极其变态,数量令人咂舌,因此只能使用scanf和printf,经测试,使用int并不会爆掉,还请放心使用int哦。


将所有数据输入完后,就可以进行计算部分了

首先计算偏移值的相反数

ansx=ax[i]*-1;//计算x偏移值的相反数
ansy=ay[i]*-1;//计算y偏移值的相反数

这里为了防止数组越界,计算敌人的位移向量时要分情况讨论,直接计算要移动的代码如下:

if(i!=1){
			ansx=(ax[j]*-1)+((bx[i-1]-bx[i])*-1);
			ansy=(ay[j]*-1)+((by[i-1]-by[i])*-1);
		}else{
			ansx=(ax[j]*-1)+bx[i];
			ansy=(ay[j]*-1)+by[i];
		}

接着在每次循环结束时输出即可,完整代码如下:

#include<bits/stdc++.h>
using namespace std;
int ax[1000005],ay[1000005],bx[1000005],by[1000005];
int main(){
	freopen("A.in","r",stdin);
	freopen("A.out","w",stdout);
	int n,m,ansx,ansy,j;
	scanf("%d%d",&n,&m);
	ax[1]=0;
	ay[1]=0;
	for(int i=2;i<=n;i++){
		scanf("%d%d",&ax[i],&ay[i]);
	}
	for(int i=1;i<=m;i++){
		scanf("%d%d",&bx[i],&by[i]);
	}
	for(int i=1;i<=m;i++){
		j++;
		if(j>n){
			j=1;
		}
		if(i!=1){
			ansx=(ax[j]*-1)+((bx[i-1]-bx[i])*-1);
			ansy=(ay[j]*-1)+((by[i-1]-by[i])*-1);
		}else{
			ansx=(ax[j]*-1)+bx[i];
			ansy=(ay[j]*-1)+by[i];
		}
				
			printf("%d %d\n",ansx,ansy);
		
	}
	return 0;
}

题.结.感.看(良语翻译官:题解结束!感谢大家的观看!)

评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值