P10132 [USACO24JAN] Cannonball B
jiangjiangQwQ · · 题解
思路
数据范围不大,但是要考虑触发一个跳板之后弹到另一个跳板又恰好跳回原来的位置,这样会死循环,解决方法有两种,一种就是限制跳的次数,一种就是记录到达这个跳板时的信息,下次到达判断是否重复跳过。对于两个方向跳跃,可以设置一个方向变量,取值为
代码
#include<iostream>
#include<map>
using namespace std;
const int N=2e5+5;
int n,s,q[N],v[N];
bool vis[N];
int sum,cnt;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>s;
for(int i=1;i<=n;i++){
cin>>q[i]>>v[i];
if(q[i]==1) cnt++;
}
int nl=1,f=1,tot=0;//nf表示当前能量
//f是方向变量,tot是我的跳跃次数
while(s<=n&&s>=1&&sum<cnt&&tot<=n*3){
++tot;
if(q[s]==1&&nl>=v[s]){//遇到目标
if(vis[s]==0) sum++;//之前没有摧毁
vis[s]=1;//标记已摧毁
}
else if(q[s]==0){//遇到跳板
nl+=v[s];//能量值变化
f=-f;//方向取反
vis[s]=1;//标记访问
}
s+=nl*f;//移动位置
}
cout<<sum;//输出摧毁的目标数
return 0;
}