luogu#P7877. 「SWTR-7」Spider Solitaire
「SWTR-7」Spider Solitaire
题目背景
题目描述下方有简化题意。
小 A 在玩蜘蛛纸牌。
为了方便你理解蜘蛛纸牌,小 A 给出了简化后的游戏规则:
- 一副牌有 张,从小到大分别为 。
- 现有 个牌堆, 副牌。每个牌堆中有 张或多张牌。
- 定义「龙」 为满足 的任意多张连续的牌。一张牌也是一个「龙」。
- 一组连续的牌可以移动,当且仅当这组牌形成了一个「龙」,且「龙」在牌堆的最右边。
- 一组连续的牌只能移动到一个非空牌堆的最右边,且必须满足可以与该非空牌堆最右边的「龙」构成一条更大的「龙」。
- 游戏胜利,当且仅当所有的 张牌形成了一个「龙」。
例如当 ,,局面为
9 8 4 3 2 1
7 5
6
时,第一个牌堆最右边的 4 3 2 1
形成了一个「龙」,所以 4 3 2 1
可以移动。将 4 3 2 1
移动到第二个牌堆的最右边,此时局面为
9 8
7 5 4 3 2 1
6
接下来将第二个牌堆右边的 5 4 3 2 1
移动到第三个牌堆的最右边,此时局面为
9 8
7
6 5 4 3 2 1
接下来将第三个牌堆的 6 5 4 3 2 1
移动到第二个牌堆的最右边,此时局面为
9 8
7 6 5 4 3 2 1
\
接下来将第二个牌堆的 7 6 5 4 3 2 1
移动到第一个牌堆的最右边,此时牌堆为
9 8 7 6 5 4 3 2 1
\
\
因为所有 张牌形成了一个「龙」,所以游戏胜利。
题目描述
给定一个蜘蛛纸牌初始局面,小 A 想知道能否获得胜利。若能,请输出 以及获胜所需的最小步数。否则输出 。
小 A 还想知道,对于每张牌 ,如果要移动 至少需要多少步,包括移动 的这一步。如果无法移动输出 -1
。
「简化题意」
有 个横向的数堆,数堆里共有 个数,每个数堆里有 或多个数。所有数堆里的数组成了 中的所有数。
你可以将一个数堆最右边递减且公差为 的连续若干个数 按照原来的顺序移到另外一个非空数堆的最右边,当且仅当该非空数堆最右边的一个数 。
求将所有的 个数都移动到同一个数堆且满足从左往右依次递减的最小步数。如果无解输出 。
此外,你还需要对于每个数 ,输出如果要移动 至少需要多少步。
输入格式
第一行一个整数 ,表示子任务编号。
第二行两个整数 ,分别表示一副牌的张数和牌堆的个数。
接下来 行,每行首先一个整数 表示该牌堆中牌的个数,接下来 个整数 从左到右描述这个牌堆。
输出格式
如果能够获胜,在第一行输出 ,第二行输出最少步数。否则输出一行 。
无论是否能够获胜,你还需输出 行,第 行一个介于 与 之间的整数,表示移动 至少需要多少步。
0
9 3
6 9 8 4 3 2 1
2 7 5
1 6
YES
4
1
1
1
1
1
2
3
-1
-1
0
13 4
4 13 10 1 7
3 11 4 8
4 6 5 3 2
2 12 9
YES
10
2
2
2
3
3
3
1
1
3
6
7
8
-1
0
5 1
5 5 4 3 2 1
YES
0
-1
-1
-1
-1
-1
0
17 10
2 12 14
1 3
3 1 13 15
0
2 9 8
1 5
3 16 7 6
2 11 2
1 4
2 17 10
YES
14
4
1
1
1
1
1
1
1
1
2
3
4
3
1
2
4
-1
0
13 4
4 10 1 13 7
4 11 12 4 8
4 6 5 3 2
1 9
NO
-1
2
2
3
3
3
1
1
-1
-1
6
5
-1
提示
「样例 1 说明」
因为 1,2,3,4,5 可以直接移动,所以至少需要 1 步即可移动。
因为需要先将 5 移至 6 右侧,6 才能移动,所以至少需要 2 步即可移动。
因为需要先将 5 移至 6 右侧,再将 4,3,2,1 移至 5 右侧,7 才能移动,所以至少需要 3 步即可移动。
显然 8,9 无法移动。
「Special Judge」
本题使用 Special Judge,请严格遵守输出格式:
- 如果你正确输出对能否获胜的判定,且如果能够获胜,你正确输出最小步数,你将获得该测试点至少 的分数。
- 在上一部分的基础上,如果你正确输出移动每张牌的最小步数,你将获得该测试点剩下 的分数。也就是说,如果你上一部分输出错误,你在这一部分也不会获得任何分数。
- 如果你的输出格式错误,你将获得该测试点 的分数,包括但不限于只输出对能否获胜的判定。
- 需要特别注意的是,如果你不能正确求出移动每张牌的最小步数,请随机输出 之间的任意整数,否则你将获得该测试点 的分数。
- 每行结束后你都需要输出换行符,包括最后一行。
checker 将在题目最后给出。
「数据范围与约定」
本题采用捆绑测试。
- Subtask #0(0 points):是样例。
- Subtask #1(15 points):,。
- Subtask #2(15 points):,。
- Subtask #3(25 points):,。
- Subtask #4(30 points):。
- Subtask #5(15 points):无特殊限制。
对于 的数据,。时间限制 1s,空间限制 512MB。
「题目来源」
Sweet Round 07 D。
idea & solution & data:Alex_Wei;验题:chenxia25。
以下是 checker,你需要有 testlib.h 才能成功编译。
#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair <int,int>
#define fi first
#define se second
#define pb emplace_back
#define mp make_pair
#define vint vector <int>
#define vpii vector <pii>
#define all(x) x.begin(),x.end()
#define sor(x) sort(all(x))
#define rev(x) reverse(all(x))
#define mem(x,v) memset(x,v,sizeof(x))
#define rint inf.readInt
#define reof inf.readEof()
#define reoln inf.readEoln()
#define rspace inf.readSpace()
// wrong answer : quitf(_wa,"The answer is wrong")
// accepted : quitf(_ok,"The answer is correct")
// partly correct : quitp(0.5,"The answer is partly correct")
int main(int argc,char* argv[]){
registerTestlibCmd(argc,argv);
string jans=ans.readToken();
string pans=ouf.readToken(jans);
int sub=rint(),n=rint(),diff=0;
if(jans=="YES"){
int jstep=ans.readInt();
int pstep=ouf.readInt();
if(jstep!=pstep)quitf(_wa,"The answer is wrong");
}
for(int i=1;i<=n;i++){
int jans=ans.readInt();
int pans=ouf.readInt();
if(jans!=pans)diff=1;
}
while(!ouf.seekEof())ouf.readToken();
while(!inf.seekEof())inf.readToken();
while(!ans.seekEof())ans.readToken();
if(diff)quitp(0.4,"The answer is partially correct");
else quitf(_ok,"OK, you AK IOI");
return 0;
}