题解:P17306 [ICPC 2026 Xi'an I] Yesterday Once More (Hard Version)
lailai0916 · · 题解
题意简述
棋盘有
解题思路
设第
总长度为:
它严格不超过限制。下面分三个阶段证明。
先执行 RDLD 块的四次尝试,可以得到以下结论:
- 若这个块没有下降,当前位置必须在某一侧边界;
- 从左上角按此前同样的块到达的状态中,右边界的停滞形态不会出现;
- 唯一可达的停滞状态是
(r,1) ,且p_r=2 、p_{r+1}=1 。
说明第二点。若一个块在非边界位置两次向下都失败,下一行唯一的障碍必须同时位于两次向下的目标列,所以中间的横向移动也必须失败。当前行只有一个障碍,这只能在边界形成局部封锁。右边界封锁要求当前行障碍在左侧一格;但第一次到达该边界时,正是依靠这一障碍挡住 L。同一块随后的第二次 D 会立刻越过封锁所需的下一行,无法留下右边界停滞。左边界则可以由 R 被当前行障碍挡住而形成上述状态。
因此,每个非停滞块至少下降一行。执行
此时
只需处理这个停滞状态。沿左上方向寻找包含
当前位置 URRD:
U到达上一行;- 第一个
R前进一步; - 第二个
R被上一行的障碍p_{i-1}=p_i+1 挡住; D被当前行的障碍p_i 挡住。
结束位置是
到达 URRD。上一行的 R 都能执行,随后 D 回到第
从
剩余的 URRD 块不会把人带回障碍左侧。每个块结束时仍在第 L,一定会被第
最后执行 DL。由于 D 不会再受阻,并必然到达第
构造字符串需要
正确性证明
第一阶段的块不使行号下降。除唯一可达的左边界封锁外,每个块至少下降一行,所以
第二阶段中,只要仍位于最长斜线左侧,一个 URRD 就准确上升一行并保持在下一障碍左侧。到达最高障碍后,列唯一性与斜线最大性保证下一块能绕到右侧。所需块数最多为
第三阶段把人移到障碍列
参考代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin>>n;
string ans;
for(int i=0;i<n;i++)ans+="RDLD";
for(int i=2;i<n;i++)ans+="URRD";
for(int i=1;i<n;i++)ans+='L';
ans+="DL";
for(int i=1;i<n;i++)ans+='D';
cout<<ans.size()<<'\n';
cout<<ans<<'\n';
return 0;
}