【hdu 1112】The Proper Key
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 487 Accepted Submission(s): 157
Problem Description
Many people think that Tetris was invented by two Russian programmers. But that is not the whole truth. The idea of the game is very old – even the Egyptians had something similar. But they did not use it as a game. Instead, it was used as a very complicated lock. The lock was made of wood and consisted of a large number of square fields, laid out in regular rows and columns. Each field was either completely filled with wood, or empty. The key for this lock was two-dimensional and it was made by joining square parts of the same size as the fields of the lock. So they had a 2D lock and 2D key that could be inserted into the lock from the top. The key was designed so that it was not possible to move it upwards. It could only fall down and it could slide sideways – exactly like in a Tetris game. The only difference is that the key could not be rotated. Rotation in Tetris is really a Russian invention.
The entry gate into the Pyramid has such a lock. The ACM archaeologists have found several keys and one of them belongs to the lock with a very high probability. Now they need to try them out and find which one to use. Because it is too time-consuming to try all of them, it is better to begin with those keys that may be inserted deeper into the lock. Your program should be able to determine how deep a given key can be inserted into a given lock.
Input
The input consists of T test cases. The number of them (T) is given on the first line of the input file. Each test case begins with a line containing two integers R and C (1 <= R,C <= 100) indicating the key size. Then exactly R rows follow, each containing C characters. Each character is either a hash mark (#) or a period (.). A hash mark represents one square field made of wood; a period is an empty field. The wooden fields are always connected, i.e. the whole key is made of one piece. Moreover, the key remains connected even if we cut off arbitrary number of rows from its top. There is always at least one non-empty field in the top-most and bottom-most rows and the left-most and right-most columns.
After the key description, there is a line containing two integers D and W (1 <= D <= 10000, 1 <= W <= 1000). The number W is the lock width, and D is its depth. The next D lines contain W characters each. The character may be either a hash mark (representing the wood) or a period (the free space).
Output
Your program should print one line of output for each test case. The line should contain the statement “The key falls to depth X.”. Replace X with the maximum depth to which the key can be inserted by moving it down and sliding it to the left or right only. The depth is measured as the distance between the bottom side of the key and the top side of the lock. If it is possible to move the key through the whole lock and take it away at the bottom side, output the sentence “The key can fall through.”.
Sample Input
4
2 4
#.##
###.
3 6
#....#
#....#
#..###
2 3
##.
.##
2 7
#.#.#.#
.#.#.#.
1 1
#
1 10
###....###
3 2
##
.#
.#
1 5
#.#.#
Sample Output
The key falls to depth 2.
The key falls to depth 0.
The key can fall through.
The key falls to depth 2.
【题目链接】:http://acm.hdu.edu.cn/showproblem.php?pid=1112
【题解】
让你那上面那个钥匙去插入下面那个锁里面;
问你这个钥匙能插多深.
这里的深度是指钥匙最后的底部和锁的上部的高度差;
我们首先可以让锁和钥匙左对齐;
即它们两个都靠左摆好;
设钥匙的高为n宽为m;
设锁的高为nn宽为mm
则钥匙能够往右移动的最大限度是mm-m;
(这道题的设置是,如果钥匙的宽比锁长就直接输出0);
也就是说你一开始有mm-m+1个位置可以插入;
而且钥匙插入锁里面之后可以左右移动(也有mm-m+1个位置可供移动);
深度的最大值为n+nn-1,一旦大于这个值就完全插入了;
代码的模拟过程是,一个单位一个单位地把钥匙往下移动;
先看看锁能在第一层的那mm-m+1个口中的哪一些口插入;
用can[r][mm-m]表示;->bool数组;
然后从第二层开始,就可能有横移操作了;
即可能can[1][j]这个状态(就是说从第j个口不能插入);
但是can[2][j-1]这个状态(第j-1个口,能一直插到第2行)可行;
那么就能从can[2][j-1]这个状态表示的情况,再右移一位;那么就能达到
can[2][j]了;这时can[2][j]不是表示从第j个口直接往下移动2层;
而是先从第j-1个口往下移动两层,再往右移动一层;
(我说的口是下面这个图所示的意思,一共mm-m+1个口)
然后如果新获得了状态can[i][j]
那么如果can[i][j-1]为false;
则让j减去1(在循环体里面要减去2,因为有个j++还没执行);
然后再看看can[i][j-1]能不能因为can[i][j]变成true了,然后can[i][j-1]本身也变成true;
(即左移)
这里判断能不能到can[i][j]这个状态.
可以看一下是钥匙的一部分的地方(x,y)
其(x+i,y+j)是不是锁;
如果是钥匙的地方(x,y),对应的(x+i,y+j)都为空,就表示这个状态可以装得下这把钥匙;
同时因为can[i-1][j]或can[i][j-1]或can[i][j+1]为true;
就说明这个位置能通过移动和外界联系;则可行;
具体的看代码吧;
【完整代码】
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100+100;
int T;
int n,m,nn,mm;
bool key[MAXN][MAXN],loc[10010][1010],can[10010][1010];
char s[1000+100];
bool in(int px,int py)
{
for (int i = 1;i <= n;i++)
for (int j = 1;j <= m;j++)
if (key[i][j] && loc[i+px][j+py])
return false;
return true;
}
int main()
{
//freopen("F:\\rush.txt","r",stdin);
cin >> T;
while (T--)
{
for (int i = 1;i <= 100;i++)
for (int j = 1;j <= 100;j++)
key[i][j] = false;
for (int i = 1;i <= 10000;i++)
for (int j = 0;j <= 1000;j++)
loc[i][j] = can[i][j] = false;
cin >> n >> m;
for (int i = 1;i <= n;i++)
{
scanf("%s",s+1);
for (int j = 1;j <= m;j++)
if (s[j]=='#')
key[i][j] = true;
}
cin >> nn >> mm;
nn+=n;
for (int i = n+1;i <= nn;i++)
{
scanf("%s",s+1);
for (int j = 1;j <= mm;j++)
if (s[j]=='#')
loc[i][j] = true;
}
for (int i = 0;i <= mm;i++)
can[0][i] = true;
int i;
for (i = 1;i <= nn;i++)
{
bool flag = false;
for (int j = 0;j <= mm-m;j++)
{
if (can[i][j]) continue;
bool judge1 = (j-1>=0 && can[i][j-1]);
bool judge2 = (j+1<=mm-m && can[i][j+1]);
bool judge3 = can[i-1][j];
if (judge1 || judge2 || judge3)
{
if (in(i,j))
{
flag = true;
can[i][j] = true;
if (j-1>=0 && !can[i][j-1])
j-=2;
}
}
}
if (!flag)
break;
}
if (i>nn)
puts("The key can fall through.");
else
printf("The key falls to depth %d.\n",i-1);
}
return 0;
}
【hdu 1112】The Proper Key的更多相关文章
- 【HDU 5647】DZY Loves Connecting(树DP)
pid=5647">[HDU 5647]DZY Loves Connecting(树DP) DZY Loves Connecting Time Limit: 4000/2000 MS ...
- 【数位dp】【HDU 3555】【HDU 2089】数位DP入门题
[HDU 3555]原题直通车: 代码: // 31MS 900K 909 B G++ #include<iostream> #include<cstdio> #includ ...
- -【线性基】【BZOJ 2460】【BZOJ 2115】【HDU 3949】
[把三道我做过的线性基题目放在一起总结一下,代码都挺简单,主要就是贪心思想和异或的高斯消元] [然后把网上的讲解归纳一下] 1.线性基: 若干数的线性基是一组数a1,a2,a3...an,其中ax的最 ...
- 【HDU 2196】 Computer(树的直径)
[HDU 2196] Computer(树的直径) 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 这题可以用树形DP解决,自然也可以用最直观的方法解 ...
- 【HDU 2196】 Computer (树形DP)
[HDU 2196] Computer 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 刘汝佳<算法竞赛入门经典>P282页留下了这个问题 ...
- 【HDU 5145】 NPY and girls(组合+莫队)
pid=5145">[HDU 5145] NPY and girls(组合+莫队) NPY and girls Time Limit: 8000/4000 MS (Java/Other ...
- 【hdu 1043】Eight
[题目链接]:http://acm.hdu.edu.cn/showproblem.php?pid=1043 [题意] 会给你很多组数据; 让你输出这组数据到目标状态的具体步骤; [题解] 从12345 ...
- 【HDU 3068】 最长回文
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=3068 [算法] Manacher算法求最长回文子串 [代码] #include<bits/s ...
- 【HDU 4699】 Editor
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=4699 [算法] 维护两个栈,一个栈放光标之前的数,另外一个放光标之后的数 在维护栈的同时求最大前缀 ...
随机推荐
- 【JZOJ3886】【长郡NOIP2014模拟10.22】道路维护
CCC 最近徆多人投诉说C国的道路破损程度太大,以至亍无法通行 C国的政府徆重视这件事,但是最近财政有点紧,丌可能将所有的道路都进行维护,所以他们决定按照下述方案进行维护 将C国抽象成一个无向图,定义 ...
- @Transactional注解事务
打了这个注解的类或者方法表示该类里面的所有方法或者这个方法的事务由spring处理,来保证事务的原子性,即方法里面对数据库操作,如果失败则spring负责回滚操作,成功提交操作 一.特性 1.serv ...
- 阿里云对象存储OSS支持版本管理特性
阿里云对象存储OSS现已经全面支持“对象版本管理”特性.该功能适用于所有的存储类型以及区域.当Bucket启用该特性后,“对象版本管理”功能可以保护和恢复误删除.误覆盖的数据. 对象存储OSS“版本管 ...
- Android Binder设计与实现 – 设计篇
摘要 Binder是Android系统进程间通信(IPC)方式之一.Linux已经拥有管道,system V IPC,socket等IPC手段,却还要倚赖Binder来实现进程间通信,说明Binder ...
- Oracle日期
oracle 日期格式 to_date("要转换的字符串","转换的格式") 两个参数的格式必须匹配,否则会报错. 即按照第二个参数的格式解释第一个参数. ...
- @游记@ CSP2019
目录 @day -??@ @day -1@ @day 0@ @day 1@ @day 2@ @day ??@ @day ??+1@ @day -??@ 和 yhn 学长在校外偶遇. 聊了一些.他说现在 ...
- MyBatis动态批量插入、更新Mysql数据库的通用实现方案
一.业务背景 由于需要从A数据库提取大量数据同步到B系统,采用了tomikos+jta进行分布式事务管理,先将系统数据源切换到数据提供方,将需要同步的数据查询出来,然后再将系统数据源切换到数据接收方, ...
- 一 linux安装python3
参考 https://www.cnblogs.com/pyyu/p/7402145.html?tdsourcetag=s_pcqq_aiomsg 1 下载 网址:https://www.python. ...
- Java练习 SDUT-2504_多项式求和
多项式求和 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 多项式描述如下: 1 - 1/2 + 1/3 - 1/4 + ...
- Hessian轻量级二进制远程调用框架
Hessian轻量级二进制远程调用框架 Hessian是一个轻量级的二进制远程调用框架,官方文档地址,它主要包括Hessian远程调用协议.Hessian序列化协议以及客户端服务端代理等几部分,关于H ...