题目

一 个NxM(N, M <= 1000)的矩阵形成星空,矩阵中的点有两种字符,'#'代表星星,'.'代表空白,星空中的星星最多5000个;给出K(K<=20)个星图,每 个星图都是HxW(H, W <= 100)的矩阵,矩阵中的点有两种字符,'#'代表星星,'.'代表空白,星图中的星星最多20个。问给出的K个星图在给出的星空中能否找到?

字符匹配问题,最简单粗暴的就是直接枚举。但是分析一下复杂度,发现直接暴力枚举复杂度为:(1000x1000x100x100x20),显然不行。
    继续分析一下题中给出的数字,“星空中的星星最多5000个,星图中的星星最多20个”,根据这个条件,考虑存储星空和星图中的那些星星的坐标,将数据进行压缩,然后看星图中的星星坐标(可能经过移动)能否从星空中找到。
    这本是一个很好的开始!但之后,我就开始了傻逼模式:试图将星图分别在x方向和y方向上进行平移,然后得到新的星星坐标,再从星空中星星坐标库中
查找是否有移动后的星星坐标,期间还很自以为机智的使用二分查找加快速度。。。。但是,没有发现这样做的时间复杂度为
(1000x1000x20xlog(5000)) 仍然很大。。
    网上看了别人的做法,发现只需要将星空中的每一个星星位置作为星图中星星的起始点(从上到下,左到右遇到的第一个星星位置),然后根据星图中星星
之间的相对位置,找到将星图起始点对应过去之后,星图中星星在星空中的位置,判断该位置处是否为一颗星星。这样,直到在星空中找到一颗星星作为星图中星星
的起始星星,这样对应之后,星图中的所有星星在星空中的位置都有星星对应,就可以判断星空中存在该星图。这样时间复杂度为(5000x20x20)
    这道题提交了十多遍,我屮艸芔茻。。我真是一个大傻逼啊!
    现在反思一下自己当时的几个失误:
(1)进行第一步简化之后,没有继续分析复杂度,放弃了继续简化的机会;
(2)简化,存储星空中星星的坐标时,就把星空的整体数据给丢掉了(没有想到存储星空中每个点是什么)。这样在之后查找的时候,用二分,而不是直接判断。。

实现

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<unordered_map>
#include<list>
#include<string>
#include<string.h>
#include<set>
#include<queue>
using namespace std;
int cons_star_c[25][25];
int cons_star_r[25][25];
int cons_width[25];
int cons_height[25];
int stars_c[5005];
int stars_r[5005];
int cons_star_count[25];
int stars_total_count;
int stars_width;
int stars_height;
char map[1005][1005]; bool findConstellation(int k) {
for (int i = 0; i < stars_total_count; i++) {
int j = 0;
for (; j < cons_star_count[k]; j++) {
int col = cons_star_c[k][j] - cons_star_c[k][0] + stars_c[i];
int row = cons_star_r[k][j] - cons_star_r[k][0] + stars_r[i];
if (!(col >= 0 && col < stars_width && row >= 0 && row < stars_height)) {
break;
}
else if (map[row][col] == '.') {
break;
}
}
if (j == cons_star_count[k])
return true;
}
return false;
}
int main() {
int K, H, W;
char symbol;
cin >> K;
scanf("%d", &K);
for (int i = 0; i < K; i++) {
cin >> H >> W;
cons_height[i] = H;
cons_width[i] = W;
int star_count = 0;
for (int row = 0; row < H; row++) {
for (int col = 0; col < W; col++) {
cin >>symbol;
if (symbol == '#') {
cons_star_r[i][star_count] = row;
cons_star_c[i][star_count] = col;
star_count++;
}
}
}
cons_star_count[i] = star_count;
} cin >> H >> W;
stars_width = W;
stars_height = H;
stars_total_count = 0;
for (int row = 0; row < H; row++) {
for (int col = 0; col < W; col++) {
cin >>symbol;
map[row][col] = symbol;
if (symbol == '#') {
stars_r[stars_total_count] = row;
stars_c[stars_total_count] = col;
stars_total_count++;
}
}
}
for (int i = 0; i < K; i++) {
if (findConstellation(i))
printf("Yes\n");
else
printf("No\n");
}
return 0;
}

hiho1099_constellation的更多相关文章

随机推荐

  1. 转载-python学习笔记之常用模块用法分析

    内置模块(不用import就可以直接使用)   常用内置函数   help(obj) 在线帮助, obj可是任何类型 callable(obj) 查看一个obj是不是可以像函数一样调用 repr(ob ...

  2. Linux(centOS6.5)下SVN的安装、配置及开机启动

    http://www.blogjava.net/rockblue1988/archive/2014/11/19/420246.aspx

  3. c#复习阶段

    在控制台程序中使用结构体.集合,完成下列要求项目要求:一.连续输入5个学生的信息,每个学生都有以下4个内容:1.序号 - 根据输入的顺序自动生成,不需要手动填写,如输入第一个学生的序号是1,第二个是2 ...

  4. 方法参数out

    using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace _050505 ...

  5. Java CSV操作(导出和导入)

    Java CSV操作(导出和导入)  CSV是逗号分隔文件(Comma Separated Values)的首字母英文缩写,是一种用来存储数据的纯文本格式,通常用于电子表格或数据库软件.在 CSV文件 ...

  6. Java一些动手动脑实验

    一.Java字段初始化的规律: 输出结果为:100 和 300 当把{filed=200}放在public int field=100之后输出结果为:200 和 300 所以执行类成员定义时指定的默认 ...

  7. 关于打开MTK_SDCARD_SWAP 宏后MTK目前升级方案和 关于打开MTK_SHARED_SDCARD宏后MTK目前升级方案

    如果设置宏MTK_SDCARD_SWAP=yes:默认是优先从外卡获取升级包,外卡没有包,才会去内卡获取!   1.插入外卡,升级包update.zip放入外卡,升级可以成功!   2.插入外卡,升级 ...

  8. 树的prufer编码

    prufer是无根树的一种编码方式,一棵无根树和一个prufer编码唯一对应,也就是一棵树有唯一的prufer编码,而一个prufer编码对应一棵唯一的树. 第一部分:树编码成prufer序列. 树编 ...

  9. C++函数前和函数后加const修饰符区别

    class Test(){ public: Test(){} const int foo(int a); const int foo(int a) const; }; 一.概念 当const在函数名前 ...

  10. C++ 函数后加const

    1.非静态成员函数后面加const(加到非成员函数或静态成员后面会产生编译错误)2.表示成员函数隐含传入的this指针为const指针,决定了在该成员函数中,    任意修改它所在的类的成员的操作都是 ...