soj1566补兵

13 篇文章 0 订阅

补兵

Time Limit:1000MS  Memory Limit:65536K
Total Submit:206 Accepted:29

Description

在非常流行的DOTA游戏中,补兵是非常重要的一种技术统计。如果一个单位被对方的多个单位攻击至死,则对该单位造成最后一次(致命的)伤害的攻击者将会获得更多的奖励(金钱和经验),这名攻击者被记录一次补兵。

现在有N个人(编号为1、2、...、N)攻击对方的一个单位。假设每人每次攻击的伤害和每两次攻击之间的间隔都是固定的。输入将给出每个人两次攻击之间的间隔时间,并假设每个人第一次攻击的时刻值就是他的两次攻击之间的时间间隔值。例如,一个人攻击间隔为2,则他会在时刻2、4、6、8……进行攻击。时间以整数计算。

如果多个人同时攻击导致对方死亡,攻击伤害最大的那个被记录一次补兵。如果攻击伤害最大的不止一个,则其中编号最小的人被记录一次补兵。

一个单位血量小于等于0就被判为死亡。

你的任务是求出对方单位死亡的时刻和被记录一次补兵的那个人的编号。

Input

输入的第一行包含一个整数M (1 < M ≤ 100),表示测试数据的组数。
每组数据第一行包含两个整数N (2 ≤ N ≤ 1000)和H (1 < H ≤ 1000000),表示攻击对方某个单位的人数和对方单位的血量。
接下来有N行,每行两个整数,分别表示每个人每次攻击的伤害A (1 ≤ A ≤ 100),以及每两次攻击之间的间隔T (1 ≤ T ≤ 100)。

Output

对每组数据,输出一行,对方单位死亡的时刻和被记录一次补兵的那个人的编号,用空格隔开。

Sample Input

2
2 10
2 2
3 3
2 10
5 3
2 10

Sample Output

6 2
6 1



校oj上的一道题,我是这么想的,求出所有士兵单位时间的攻击值,相加后可以得到大概在什么时候boss会被打死,然后再搜索是哪个士兵补到了兵。这样复杂度就不会很高,但是我做了一天多的时间一直wa,就在我wa到欲仙欲死的时候,才发现,原来是一个出乎我意料的非常简单的错误导致wa,就是数组开小了。。。。小了。恩不说了我去抽自己几巴掌

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define MAX 110
#define MAXM 1010
#define LL long long
using namespace std;

LL N,H,s[MAXM][2];//这个地方开成了MAX。。。

struct OnceHurt{
	LL t,hurt,who;
	bool operator<(OnceHurt a)const{
		if(t<a.t)return true;
		if(t>a.t)return false;
		if(hurt>a.hurt)return true;
		if(hurt<a.hurt)return false;
		if(who<a.who)return true;
		return false;
	}
}hurts[MAX*MAXM];

int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		scanf("%lld %lld",&N,&H);
		double expect=0.0;
		LL expecttime,hurt=0;
		for(LL i=0;i<N;i++){
			scanf("%lld %lld",&s[i][0],&s[i][1]);
			expect+=double(s[i][0])/s[i][1];
		}
		expecttime=max((LL)(H/expect)-1,0LL);
		for(LL i=0;i<N;i++){
			hurt+=expecttime/s[i][1]*s[i][0];
		}
		LL j=0;
		for(LL i=0;i<N;i++){
			LL t=expecttime/s[i][1]*s[i][1]+s[i][1]-expecttime;
			while(t<MAX){
				hurts[j].t=t,hurts[j].hurt=s[i][0],hurts[j].who=i+1;
				j++;
				t+=s[i][1];
			}
		}
		sort(hurts,hurts+j);
		for(LL i=0;i<j;i++){
			hurt+=hurts[i].hurt;
			if(hurt>=H){
				LL anst=expecttime+hurts[i].t,who=hurts[i].who;
				for(int p=i-1;hurts[p].t+expecttime==anst&&p>=0;p--){
						who=hurts[p].who;
				}
				printf("%lld %lld\n",anst,who);
				break;
			}
		}
	}	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值