题目1 : 大礼堂地毯
-
2 3 3 ABC ABD 3 3 BCA BDA BCA 2 3 BAC BAD 7 14 ABCABCABCABCAB ABDABDABDABDAB ABCABCABCABCAB ABDABDABDABDAB ABCABCABCABCAB ABDABDABDABDAB ABCABCABCABCAB
样例输出
-
YES NO YES
描述
小Hi的学校大礼堂的地毯是由很多块N × M大小的基本地毯拼接而成的。例如由2×3的基本地毯
ABC ABD
拼接而成的大礼堂整片地毯如下:
... ABCABCABCABCAB ABDABDABDABDAB . ABCABCABCABCAB . . ABDABDABDABDAB . . ABCABCABCABCAB . ABDABDABDABDAB ABCABCABCABCAB ...
由于大礼堂面积非常大,可以认为整片地毯是由基本地毯无限延伸拼接的。
现在给出K张地毯的照片,请你判断哪些照片可能是小Hi学校大礼堂地毯的一部分。不需要考虑旋转照片的方向。
例如
BCA BDA BCA
可能是上述地毯的一部分,但
BAC BAD
不可能是上述地毯的一部分。
输入
第1行包含三个整数,N,M 和 K。
第2~N+1行包含一个N × M的矩阵,代表基本地毯的样式。其中每一个元素都是一个大写字母(A-Z)。
之后是 K 张照片的数据。
每张照片的第一行包含两个整数,H 和 W,代表照片的大小。
以下 H 行包含一个 H × W的矩阵,代表照片中地毯的样式。其中每一个元素都是一个大写字母(A-Z)。
对于80%的数据,1 ≤ N, M ≤ 10, 1 ≤ H, W ≤ 100
对于100%的数据, 1 ≤ N, M ≤ 50, 1 ≤ K ≤ 10, 1 ≤ H ≤ 100, 1 ≤ W ≤ 800。
输出
对于每张照片,输出YES或者NO代表它是否可能是大礼堂地毯的一部分。
解析:判断是不是由基本地毯组成的,只需要将基本地毯扩大的足够大,然后用滚动数组判断即可
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1000009;
char tp[59][59], mp[1009][1009], s[1009][1009];
int n, m, w, h;
bool judge()
{
for(int i = 0; i < m; i++) strcpy(s[i], tp[i]);
int num = n;
while(num <= w)
{
for(int i = 0; i < m; i++)
strcat(s[i], tp[i]);
num += n;
}
int k = 0;
for(k = 0; k < m; k++) if(strstr(s[k], mp[0])) break;
if(k >= m) return false;
k = (k + 1) % m;
for(int i = 1; i < h; i++)
{
if(strstr(s[k], mp[i])) k = (k + 1) % m;
else return false;
}
return true;
}
int main()
{
int k;
scanf("%d%d%d", &m, &n, &k);
for(int i = 0; i < m; i++)
{
scanf(" %s", tp[i]);
}
while(k--)
{
scanf("%d%d", &h, &w);
for(int i = 0; i < h; i++)
{
scanf(" %s", mp[i]);
}
if(judge()) puts("YES");
else puts("NO");
}
return 0;
}
//2 3 3
//ABC
//ABD
//7 14
//ABCABCABCABCAB
//ABDABDABDABDAB
//ABCABCABCABCAB
//ABDABDABDABDAB
//ABCABCABCABCAB
//ABDABDABDABDAB
//ABCABCABCABCAB
//NO
题目2 : 数组重排3
-
2 54321 321
样例输出
-
3 -1
描述
给定一个{1..N}的排列A1, A2, ... AN,每一次操作可以将相邻的两个数一起移动(保持两个数相邻且前后顺序不变)到任意位置。询问至少经过多少次操作,可以使得原序列变为1, 2, ..., N。
例如对于54321,把32一起移动到最左端得到32541;再把25一起移动到最右端得到34125;再把12一起移动到最左端得到12345。
输入
第1行:1个正整数 T,表示输入数据的组数
第2..T+1行:每行一个字符串,表示初始排列
对于30%的数据:T = 1, 1 ≤ N ≤ 5
对于100%的数据:1 ≤ T ≤ 5, 1 ≤ N ≤ 8
输出
第1..T行:每行一个整数,第i行表示第i个排列变化为1, 2, ..., N所需要的最少步数。若无可行方案,输出"-1"。
解析:BFS去搜索,用队列去枚举所有情况,map标记,遇到第一个有序的,返回次数即可
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1000009;
typedef pair<int, int> P;
int solv(char str[])
{
int d[11], len = strlen(str);
queue<P> q;
map<int, int> mp;
mp.clear();
int s, e; s = e = 0;
for(int i = 0; str[i]; i++) s = s * 10 + str[i] - '0', e = e * 10 + i + 1;
mp[s] = 1;
q.push(make_pair(s, 0));
while(!q.empty())
{
P p = q.front(); q.pop();
s = p.first;
if(s == e) return p.second;
for(int i = 0; i < len; i++) d[i] = s % 10, s /= 10;
for(int i = 0, j = len - 1; i < j; i++, j--) swap(d[i], d[j]);
int cur = 0;
for(int i = 0; i < len - 1; i++)
{
for(int j = 0; j < len - 1; j++)
{
cur = 0;
if(j + 1 == len - 1)
{
for(int k = 0; k < len; k++)
{
if(k == i || k == i + 1) continue;
cur = cur * 10 + d[k];
}
cur = cur * 100 + d[i] * 10 + d[i+1];
}
else
{
for(int k = 0; k < j; k++)
{
if(k == i || k == i + 1) continue;
cur = cur * 10 + d[k];
}
cur = cur * 100 + d[i] * 10 + d[i+1];
for(int k = j; k < len; k++)
{
if(k == i || k == i + 1) continue;
cur = cur * 10 + d[k];
}
}
if(mp[cur]) continue;
mp[cur] = 1;
q.push(make_pair(cur, p.second+1));
}
}
}
return -1;
}
int main()
{
int t;
char str[11];
scanf("%d", &t);
while(t--)
{
scanf(" %s", str);
printf("%d\n", solv(str));
}
return 0;
}