题解:P12687 [KOI 2022 Round 1] 鹅卵石
· 阅读需 2 分钟
原题链接
题意简述
给定长度为 的数组 ,每次可对相邻两点同时拿相同数量,或对单点拿任意数量,求将所有石子拿完时所需的最少操作次数。
解题思路
-
枚举每个起点 ,向右模拟交替相邻配对:维护一个变量 ,初始为 ,然后依次计算 。
-
若 且恰好等于 ,则区间 可以完全通过相邻配对消除,记录其右端点为 。否则若 则跳出,尝试下一个起点。
-
令 表示在位置 范围内,最多能选的互不重叠“可消除区间”数量。
-
对每个右端点 ,先继承 (不选任何以 结尾的区间),再遍历所有以 为右端的合法起点 ,计算其对应候选值 (若 则为 ),取最大更新 。
-
最大可配对消除区间数为 ,剩下必须单点拿的次数即 。
参考代码
#include <bits/stdc++.h>
using namespace std;
const int N=2505;
int a[N],f[N];
vector<int> G[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<n;i++)
{
int t=a[i];
for(int j=i;j<n;j++)
{
if(j>i)t=a[j]-t;
if(t<=0)break;
if(t==a[j+1])G[j].push_back(i);
}
}
for(int i=1;i<n;i++)
{
f[i]=f[i-1];
for(auto u:G[i])
{
f[i]=max(f[i],u==1?1:f[u-2]+1);
}
}
cout<<n-f[n-1]<<'\n';
return 0;
}