传送门:闯关
题目要求我们为骑士构造一个长度为 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之间呢,所以这个做法不对