hihoCoder 编程练习赛19 A, B

题目1 : 大礼堂地毯

时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB

描述

小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代表它是否可能是大礼堂地毯的一部分。

样例输入
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

解析:判断是不是由基本地毯组成的,只需要将基本地毯扩大的足够大,然后用滚动数组判断即可

代码:

#include
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

时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB

描述

给定一个{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"。

样例输入
2
54321
321
样例输出
3
-1

解析:BFS去搜索,用队列去枚举所有情况,map标记,遇到第一个有序的,返回次数即可

代码:

#include
using namespace std;
const int N = 1000009;
typedef pair P;


int solv(char str[])
{
    int d[11], len = strlen(str);
    queue

q; map 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; }



你可能感兴趣的:(hihocode)