华农acm:scau9505 射穿多少

7 篇文章 0 订阅
3 篇文章 0 订阅

题目:

9505 射了多少
时间限制:1000MS  内存限制:65535K
提交次数:676 通过次数:107

题型: 编程题   语言: G++;GCC
Description
    


    大家都知道CS中的AWP可以一枪KO人家,最爽的就是没看到别人,但知道人家在墙后而一枪穿墙爆头击毙.
    现在把CS地图定义为一个二维空间,你的位置在(x0,y0),你不知道敌人的位置(除非有间谍),因此你想尽可能多的穿过地图上的格子.
    但你不知道如何计算当他射向点(x1,y1)(到x1,y1停下来)的时候穿过了多少个格子,因此希望你这个强大的programmer帮忙



输入格式
    输入中一共有两行
    第一行是2个整数表示你的位置x0,y0(1000>=x0,y0>=0)
    第二行是2个整数表示子弹停下的位置x1,y1(1000>=x1,y1>=0)


输出格式
    输出只有一行
    穿过的格子数(碰到不算穿过任何格子,要严格穿过)


输入样例
0 0
2 2


输出样例
2


来源 ick2 

作者 a470086609

解析:

首先要知道什么是严格的射穿,射穿就是不能只是一个点,所以我们只要找到有多少个点,然后把这些点去掉够可以了。

思路:答案=总的格子数-没有射穿的格子数

这就涉及到求整数点了,而求整数点利用的算法是:扩展欧几里而算法。具体可以先去百度学习一下。它是用来求二元一次不定方程的整数解。

观察图

   平移后 

不难得出总的格子数是(dx+dy-1)

那么如果存在整数点意味着什么呢

我们只关心中心的这四块

一个整数点意味这失去了一个格子

有了这些前提条件我们现在就可以放心的利用扩展欧几里德算法来计算整数点个数。

bad = 整数点个数

all = 总射穿格子个数(上图黄色的格子)= dx+dy-1

ans = all  - bad



然后带入扩展欧几里德算法就可以了

Code:

#ifdef local
#include    <ctime>
#endif
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>
#define rep(i,e) for(int i=0;i<e;i++)
#define rep1(i,e) for(int i=1;i<=e;i++)
#define repx(i,x,e) for(int i=x;i<=e;i++)
#define ll long long
#define pii pair<int,int>
#define F first
#define S second
#define pb push_back
#define mp make_pair
#define mset(var,val) memset(var,val,sizeof(var))
#define IOS ios::sync_with_stdio(false);cin.tie(0)
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define test(a) cout<<a<<endl
#define test2(a,b) cout<<a<<" "<<b<<endl
#define test3(a,b,c) cout<<a<<" "<<b<<" "<<c<<endl
typedef unsigned long long ull;
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 1e6 + 10;
int x0;
int x1;
int y1;
int y0;
int gcd(int a, int b) {
	return b == 0 ? a : gcd(b, a % b);
}
bool isIN(int x, int y) {
	// cout << "test" << x << "," << y << endl;
	if (x == x0 && y == y0)return false;
	if (x == x1 && y == y1)return false;
	if (x < x0 || x> x1 )
		return false;
	if (y0 < y1) {
		if (y < y0 || y > y1) {

			return false;
		}
	} else {
		if (y < y1 || y > y0) {
			return false;
		}
	}
	return true;
}
void work() {

	cin >> x0 >> y0 >> x1 >> y1;
	if (x0 > x1) {
		swap(x0, x1);
		swap(y0, y1);
	}
	int a = (y0 - y1);
	int b = (x1 - x0);
	int g = gcd(abs(a), abs(b));
	int pa = a / g;
	int pb = b / g;
	int ans = abs(a) + abs(b) - 1;
	for (int i = -1100 ; i <= 1100; i++) {
		if (isIN(x0 + i * pb, y0 - i * pa)) {
			// cout << x0 + i*pb << " " << y0 - i*pa << endl;
			ans--;
		}
	}
	cout << ans << endl;
}
int main() {
	int debug = 0;
#ifdef local
	debug = 1;
#endif
	if (debug) {
		freopen("in.txt", "r", stdin);
		freopen("out", "w", stdout);
		printf("debuging output:\n");
	}
	work();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值