题解:P11116 [ROI 2024] 割草 (Day 2)
被黄题硬控两天半(虽然在集训吧)。不过是道好题。
讲一下做这题的心路历程,看到有很多部分分决定先思考子任务
Solve
题意很明确就不过多赘述了。
这里我们首先注意到要覆盖整段草坪,任意两台机器人之间的部分不能留空 —— 它们合力一定要把中间的“缝隙” 切掉。
令
考虑如何转移。假设我们已经算出了
| 前一辆 |
当前 |
可行性条件 | 说明 |
|---|---|---|---|
| 向右 | 向右 | 前一辆要跑得远一点,至少切到或越过 |
|
| 向左 | 向左 | 当前这辆要能跑到或越过 |
|
| 向右 | 向左 | 它俩相向而行,分别切一段前缀和一段后缀,两段相加至少整个空隙。 | |
| 向左 | 向右 | 不合法 | 它俩相反方向行驶,必定在它们中间留下空草坪,无法覆盖。 |
细节见代码。
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10,INF=1e9;
int n,x[N],p[N],d[N];
int f(int i,int s){//把状态 0/1 映射到方向 -1/+1
int w=(s==0?-1:1);
return w==d[i]?0:1;
}
int dp[N][2],ans;
int main(){
cin>>n;
for(int i=1;i<=n;++i)
cin>>x[i]>>p[i]>>d[i];
dp[1][0]=f(1,0);
dp[1][1]=f(1,1);
for(int i=2;i<=n;++i){
dp[i][0]=dp[i][1]=INF;//初始化
int diff=x[i]-x[i-1];
//右->右
if(p[i-1]>=diff && dp[i-1][1]<INF)
dp[i][1]=min(dp[i][1],dp[i-1][1]+f(i,1));
//左->左
if(p[i]>=diff && dp[i-1][0]<INF)
dp[i][0]=min(dp[i][0],dp[i-1][0]+f(i,0));
//右->左
if(p[i-1]+p[i]>=diff && dp[i-1][1]<INF)
dp[i][0]=min(dp[i][0],dp[i-1][1]+f(i,0));
//左->右 不合法
}
ans=min(dp[n][0],dp[n][1]);
cout<<(ans>=INF?-1:ans);//INF无解
return 0;
}
完结撒花