专栏文章
题解:AT_abc404_e [ABC404E] Bowls and Beans
AT_abc404_e题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mipdjbrl
- 此快照首次捕获于
- 2025/12/03 10:14 3 个月前
- 此快照最后确认于
- 2025/12/03 10:14 3 个月前
题目大意
有 个碗编号为 ,第 个碗中无豆子,第 个碗中有 个豆子,它的所有豆子可以移动到前 个碗中的任意一个,求将所有碗中的豆子移动到 号碗里最少需要几次移动。
解法
我们可以设计一个记忆化搜索:
对于每一个碗,我们记录有那些碗可以把豆子转移到那个碗里。
然后我们可以把它想象成最开始所有豆子都在 号碗里,我们要把所有豆子移到有豆子的那些碗里。
我们从 号碗开始,向后移动豆子。但我们注意到有豆子的碗是必须得移到的,不然它就会没有豆子,所以在搜索时,记录接下来要到哪一个碗里,每次只要可以从转到那里,那就直接转过去。
但需要注意的是,我们的记忆化搜索
dfs(x) 表示把 x 后面的碗的所有豆子都移到 x 这个碗最少需要几步,所以由于最后一个有豆子的碗及以后的所有碗后面都没有豆子,所以都为 。(赛时就因为这个没拿分)代码
CPP#include <bits/stdc++.h>
#define int long long
const int N = 1e5 + 5;
const int Mod = 1e9 + 7;
using namespace std;
int n;
int sum, ans;
int c[N], a[N];
int f[N];
vector<int> froms[N];
vector<int> toes;
int dfs(int x, int y, int to)
{
if (f[x])
{
return f[x];
}
if (x >= toes.back())
{
return 0;
}
if (x == toes[to])
{
to++;
}
int mi = 1e18;
for (int i : froms[x])
{
if (i > toes[to])
{
continue;
}
mi = min(mi, dfs(i, y + 1, to));
}
f[x] = mi + 1;
return mi + 1;
}
signed main()
{
cin >> n;
n--;
for (int i = 1; i <= n; i++)
{
cin >> c[i];
for (int j = i - c[i]; j <= i - 1; j++)
{
froms[j].push_back(i);
}
}
for (int i = 1; i <= n; i++)
{
cin >> a[i];
if (a[i])
{
toes.push_back(i);
}
}
ans = dfs(0, 0, 0);
cout << ans;
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...