【题解】CF1301D Time to Run
趣味简单题
题目链接:CF1301D 【Time to Run】
题意简介:
给定一个
这题一开始想,还以为是个什么欧拉路的题目,但是输出方案的方式给了我们提示...
输出方案最多
字符串中使用字符
这个输出方法很玄学,如果是我们找到了一种走法,再去考虑输出方案,显然我们还需要分割路径的字符串,这很麻烦。
所以考虑构造一种万能走法,能够囊括 所有的长度。
注意标黑的部分,那显然我们如果能找到一种走法,使得每一条边都能被遍历,显然就是最优的了。
我们令左上角为
我们很快可以找出一种走法,可以遍历完第一行格子之间的边,和第一行与第二行之间的所有边的走法(除了
这中间蓝色显然是可以重复走的 懒得画了,红色是
注意一下最后一行只能
最后,我们会到达
那这种做法是否符合输出规范呢?
显然处理一行,我们需要的行数为
再来看字符串长度问题,根据上面所说,我们只会走
再有
那么我们就做完了。
注意特判
因为我们的走法第一步就是
所以特判一下直接
注意每走一步新的都要判断是否在这一步中结束,因为他要最先输出命令行数,所以我就把它丢到
#include<bits/stdc++.h>
using namespace std;
int n,m,savk,k,lim;
vector<int> cnt;
vector<string> ans;
inline void print() {
puts("YES");
int len = cnt.size(),tmp;
cout << len << endl;
for(register int i = 0;i < len; ++i) {
cout << cnt[i] << ' ' << ans[i] << endl;
tmp += cnt[i] * ans[i].length();
}
return;
}//输出答案
int main () {
//freopen("in.in","r",stdin);
cin >> n >> m >> k; savk = k;
if(k > 4 * n * m - 2 * n - 2 * m) {puts("NO"); return 0;}//总共边数都没有这么多
if(m == 1) {//特判
lim = n - 1;
if(k <= lim) {
cnt.push_back(k),ans.push_back("D");
k = 0;
print();
return 0;
}// D下去
k -= lim;
cnt.push_back(lim),ans.push_back("D");
if(k <= lim) {
cnt.push_back(k),ans.push_back("U");
k = 0;
print();
return 0;
}
k -= lim;
cnt.push_back(lim),ans.push_back("U");// U上来
if(!k) print();
else puts("NO");
return 0;
}
lim = m - 1;//指红蓝两种走法最多走多少次,显然是m-1
for(register int i = 1;i <= n; ++i) {
if(k <= lim) {
cnt.push_back(k),ans.push_back("R");
k = 0;
break;
}
k -= lim;
cnt.push_back(lim),ans.push_back("R");//红
if(i < n && k <= lim * 3) {//不是最后一行并且在这一步中结束
int tmp = k / 3,_;
if(tmp) {
cnt.push_back(tmp),ans.push_back("DUL");
}
_ = k - tmp * 3;
if(_ == 1) cnt.push_back(1),ans.push_back("D");
else if(_ == 2) cnt.push_back(1),ans.push_back("DU");
k = 0;//蓝中间结束,注意最后一下是 D 还是 DU
break;
}
if(i < n) {//不是最后一行的情况
k -= lim * 3;
cnt.push_back(lim),ans.push_back("DUL");
cnt.push_back(1),ans.push_back("D");//蓝
k--;
} else {//最后一行,直接L回去
if(k <= lim) {
cnt.push_back(k),ans.push_back("L");
k = 0;
break;
} else {
k -= lim;
cnt.push_back(lim),ans.push_back("L");
}
}
if(!k) break;
}
if(!k) {//如果走完了,输出
print();
return 0;
}
if(k <= n - 1) {//否则我们可以走 U n-1次
cnt.push_back(k),ans.push_back("U");
print();
} else puts("NO");//肯定就不行了
return 0;//End.
}
趣味题,作为一道 ,注意特判,就没什么难的了。
初三的
还有一种更好写的做法
RRR DDD...到了右下
LLL...RRR...U走一行 上
LLL...RRR...U走一行 上
L DDD... UUU... 走一列
L DDD... UUU...走一列
这个好妙啊 qwq