牛客练习赛130 B

传送门:闯关

题目要求我们为骑士构造一个长度为 n 的数列,使得骑士在经过 k 步之后血量恰好降为0并死亡。

骑士从 0 号房间出发,依次进入 1 到 n 号房间。每个房间都有一个数值 a_i,如果 a_i >= 0,骑士进入后会恢复 a_i 的血量;如果 a_i < 0,则会扣除 -a_i 的血量。
骑士的初始血量为 h,并且数列中的每个数 a_i 都需要满足 L <= a_i <= R。
题目要求我们构造一个数列,使得骑士走完 k 步之后,血量恰好降至 0 或更低。
如果无法构造这样的数列,输出 impossible,否则输出一个合法的数列。

输入:

n: 房间的数量(不包含0号房间)
k: 骑士走的步数
h: 骑士的初始血量
L: 数列中的下界
R: 数列中的上界
1≤k≤n≤10^5 ,1≤h≤10^9, 1≤L≤R≤10^9
输出:

如果可以构造,输出合法数列;否则输出 impossible。
示例:

输入: 2 1 3 -4 0,输出: -3 -4
输入: 2 2 1 -1 -1,输出: impossible

分析:这题一眼就是构造题,那么好,我们分析一下不合法的情况,首先h是正数,那么l>=0肯定不合法,h永远不会等于零,同时我们要保证h+l*k<=0; 另外我们要保证前k-1步h不会等于零,所以h+(k-1)*r<=0不合法,剩下的存在合法数列。
最难的是构造合法序列,我们可以令sum=h+k*r,什么意思呢,我们先假设从1到k步我们都走r,那么最好的情况是sum,sum肯定大于0,我们从k往1遍历,如何sum>r-l,就可以将a[i]赋值为l,直到sum==0
 

/*即使这个图论(world)大的无边无际
我也会深度优先搜索(dfs)找到你..*/

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,k,h,l,r;
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin>>n>>k>>h>>l>>r;
	if(l>=0) cout<<"impossible";
	else if(h+l*k>0) cout<<"impossible";
	else if(h+(k-1)*r<=0) cout<<"impossible";
	else
	{
		ll sum = h+r*k;
		vector<ll> a(n+1);
		for(int i=1;i<=n;i++) a[i] = r;
		for(int i=k;i>=1;i--)//我们从后往前遍历,直接sum的值变为0
		{
			if(sum>r-l)
			{
				sum-=(r-l);
				a[i]=l;
			}
			else
			{
				a[i]=r-sum;
				sum = 0;
				break;
			}
		}
		for(int i=1;i<=n;i++)
			cout<<a[i]<<" \n"[i==n];
	}
	return 0;
}

然后我觉得可以构造序列的时候这样写

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,k,h,l,r;
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin>>n>>k>>h>>l>>r;
	if(l>=0) cout<<"impossible";
	else if(h+l*k>0) cout<<"impossible";
	else if(h+(k-1)*r<=0) cout<<"impossible";
	else
	{
		ll sum = h+r*k;
		vector<ll> a(n+1);
		for(int i=1;i<=n;i++) a[i] = r;
		for(int i=k;i>=1;i--)//我们从后往前遍历,直接sum的值变为0
		{
			if(sum > r-l)
			{
				sum-=(r-l);
				a[i]=l;
			}
			else
			{
				a[i]=-sum;
                sum = 0;
				break;
			}
		}
		for(int i=1;i<=n;i++)
			cout<<a[i]<<" \n"[i==n];
	}
	return 0;
}

但是只过了85%的数据,思考了一下,发现我初始设a[i]=0,万一0不在l和r之间呢,所以这个做法不对

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值