noip模拟赛 水管工的难题
【问题描述】
你是一名优秀的水管工。 一天你遇到了一个棘手的难题。 你需要在一个长方体状的房间
内连接一条贯穿房间内部的水管。房间的长为 X,宽为 Y,高为 Z, 整个房间可以看成是 X×Y×Z
个小立方体空间组成的。 如果位房间建立直角坐标系,则房间内每个小立方体空间都可以用
一个三维坐标(x,y,z)表示, 房间一角的小立方体的坐标为(1,1,1), 它的对角的坐标为(X,Y,Z),
其余小立方体的坐标的三个维度都分别落在 1…X, 1…Y 和 1…Z 内。 水管的入口和出口已经
开凿好了,它们位于长方体的表面(可能位于房间的地板、墙壁或天花板上),且正好占据
了某个小立方体的一个面。下图展示了房间的立方体空间的划分方式和一种开凿水管出入口
的方式。
你的手头只有一种形状的水管部件, 它呈 L 型,且正好占据了 4 个小立方体空间, 如下
图所示, 灰色部分是水管部件两端的开口位置。
你可以任意旋转、翻转水管部件,然后将它的开口接到入口、 出口或者其它水管部件的
开口上。 水管的开口必须正好接在入口或出口上才算接上,伸出房间外一截是不行的。 下图
展示了一种两个水管部件的连接方式。
在连接水管时, 水管部件间不能相交,也不能伸出房间之外。房间内有一些小立方体空
间已经被物品占据了,水管也不能经过那些格子。 另外,水管部件数量有限,你的手头只有
12 个这样的零件。
现在,给出房间的长、高、 宽, 以及入口、出口的位置和房间内物品的坐标,请你计算 至少需要多少个这样的水管部件才能完成任务,或者判断无法完成任务。
【输入】
输入的第 1 行包含 4 个正整数 X, Y, Z, m,其中 X,Y,Z 表示房间的长、高、宽, m 表示
房间中物品的数量。
输入的第 2 行包含 3 个正整数 x1, y1, z1, 和一个字符 ch。 其中(x1,y1,z1)是水管入口所
在的小立方体的坐标。 ch 的值为'x'、 'y'或'z', 用于指示入口所在的面。 当 ch 为'x'时,表示
入口所在的面与 YZ 坐标平面平行, 当 ch 为'y'时,表示入口所在的面与 XZ 坐标平面平行,
当 ch 为'z'时,表示入口所在的面与 XY 坐标平面平行。 输入保证入口所在的面在长方体表面
上。 数字和数字、数字和字符间用一个空格隔开。
输入的第 3 行包含 3 个正整数 x2, y2, z2,和一个字符 ch, 表示水管出口的位置, 意义
与格式同上。
接下来 m 行,每行包含三个正整数 xi, yi, zi,表示在坐标(xi,yi,zi)的小立方体空间内有
物品。
【输出】
输出包含 1 个整数,表示最少使用的水管部件的数量。 如果不能完成接水管的任务,输
出“impossible”, 不含引号。
【输入输出样例 1】
plumber.in | plumber.out |
5 4 3 1 3 1 1 z 1 4 3 x 2 3 3 |
2 |
见选手目录下的 plumber/plumber1.in 与 plumber/plumber1.out
【输入输出样例 1 说明】
入口和出口的位置如图所示:
分析:就是一道爆搜题.dfs,记录放的水管的最后一个位置和方向,除了这个方向和它对面的方向以外都可以放,然后就有两种方式了,讨论一下,枚举一下旋转方向就行了.
直接搜会T掉,要加上剪枝.可行性剪枝似乎不行,考虑最优性剪枝,如果剪枝仅仅是如果当前用的水管数>ans就返回,还是会T掉4个点,需要用上一个估价函数.考虑3维空间上的曼哈顿距离,每用一个水管当前位置与终点位置的曼哈顿距离就会-4,计算一下当前点与终点的曼哈顿距离为多少就能计算出至少还需要用多少根水管,就能最优性剪枝了.
#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; const int dx[] = { , -, , , , }, dy[] = { , , , -, , }, dz[] = { , , , , , - }; int X, Y, Z, m, ans = , tx, ty, tz, tdir, sx, sy, sz, sdir;
bool vis[][][], a[][][]; bool check(int x, int y, int z)
{
if (x >= && x <= X && y >= && y <= Y && z >= && z <= Z && !vis[x][y][z] && !a[x][y][z])
return true;
return false;
} void dfs(int x, int y, int z, int dir, int p)
{
int dis = abs(tx - x) + abs(ty - y) + abs(tz - z);
if (p + dis / >= ans)
return;
if (x == tx && y == ty && z == tz && dir == tdir)
{
ans = min(ans, p);
return;
}
if (check(x + dx[dir], y + dy[dir], z + dz[dir]) && check(x + * dx[dir], y + * dy[dir], z + * dz[dir]))
{
vis[x + dx[dir]][y + dy[dir]][z + dz[dir]] = ;
vis[x + * dx[dir]][y + * dy[dir]][z + * dz[dir]] = ;
int nx = x + * dx[dir], ny = y + * dy[dir], nz = z + * dz[dir];
for (int i = ; i < ; i++)
{
if ((i / ) != (dir / ))
{
if (check(nx + dx[i], ny + dy[i], nz + dz[i]) && check(nx + * dx[i], ny + * dy[i], nz + * dz[i]))
{
vis[nx + dx[i]][ny + dy[i]][nz + dz[i]] = vis[nx + * dx[i]][ny + * dy[i]][nz + * dz[i]] = ;
dfs(nx + * dx[i], ny + * dy[i], nz + * dz[i], i, p + );
vis[nx + dx[i]][ny + dy[i]][nz + dz[i]] = vis[nx + * dx[i]][ny + * dy[i]][nz + * dz[i]] = ;
}
}
} if (check(x + * dx[dir], y + * dy[dir], z + * dz[dir]))
{
vis[x + * dx[dir]][y + * dy[dir]][z + * dz[dir]] = ;
int nx = x + * dx[dir], ny = y + * dy[dir], nz = z + * dz[dir];
for (int i = ; i < ; i++)
{
if ((i / ) != (dir / ))
{
if (check(nx + dx[i], ny + dy[i], nz + dz[i]))
{
vis[nx + dx[i]][ny + dy[i]][nz + dz[i]] = ;
dfs(nx + dx[i], ny + dy[i], nz + dz[i], i, p + );
vis[nx + dx[i]][ny + dy[i]][nz + dz[i]] = ;
}
}
}
vis[x + * dx[dir]][y + * dy[dir]][z + * dz[dir]] = ;
}
vis[x + dx[dir]][y + dy[dir]][z + dz[dir]] = ;
vis[x + * dx[dir]][y + * dy[dir]][z + * dz[dir]] = ;
}
} int main()
{
scanf("%d%d%d%d", &X, &Y, &Z, &m);
char s[];
scanf("%d%d%d", &sx, &sy, &sz);
scanf("%s", s);
sdir = (s[] - 'x') * ; //找起点
if (s[] == 'x')
sdir += (sx == X);
else
if (s[] == 'y')
sdir += (sy == Y);
else
if (s[] == 'z')
sdir += (sz == Z);
sx -= dx[sdir];
sy -= dy[sdir];
sz -= dz[sdir];
scanf("%d%d%d", &tx, &ty, &tz);
scanf("%s", s);
tdir = (s[] - 'x') * ;
if (s[] == 'x')
tdir += (tx == );
else
if (s[] == 'y')
tdir += (ty == );
else
if (s[] == 'z')
tdir += (tz == );
for (int i = ; i <= m; i++)
{
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
a[x][y][z] = ;
}
dfs(sx, sy, sz, sdir, );
if (ans == )
printf("impossible\n");
else
printf("%d\n", ans); return ;
}
noip模拟赛 水管工的难题的更多相关文章
- noip模拟赛 水题
题目描述 LYK出了道水题. 这个水题是这样的:有两副牌,每副牌都有n张. 对于第一副牌的每张牌长和宽分别是xi和yi.对于第二副牌的每张牌长和宽分别是aj和bj.第一副牌的第i张牌能覆盖第二副牌的第 ...
- NOIP模拟赛20161022
NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...
- contesthunter暑假NOIP模拟赛第一场题解
contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...
- 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程
数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...
- 队爷的Au Plan CH Round #59 - OrzCC杯NOIP模拟赛day1
题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的Au%20Plan 题解:看了题之后觉得肯定是DP ...
- 队爷的新书 CH Round #59 - OrzCC杯NOIP模拟赛day1
题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的新书 题解:看到这题就想到了 poetize 的封 ...
- CH Round #58 - OrzCC杯noip模拟赛day2
A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...
- 10.17 NOIP模拟赛
目录 2018.10.17 NOIP模拟赛 A 咒语curse B 神光light(二分 DP) C 迷宫maze(次短路) 考试代码 B 2018.10.17 NOIP模拟赛 时间:1h15min( ...
- 10.16 NOIP模拟赛
目录 2018.10.16 NOIP模拟赛 A 购物shop B 期望exp(DP 期望 按位计算) C 魔法迷宫maze(状压 暴力) 考试代码 C 2018.10.16 NOIP模拟赛 时间:2h ...
随机推荐
- Django day 38 结算中心,支付中心,计算价格方法
一:结算中心 二:支付中心 三:计算价格方法
- java 线程开元篇
学习java的读者都知道,Java的每个对象都会有默认的12个方法,这12个方法分别是 object() finalize() hashCode() equals() wait() wait(long ...
- Akka源码分析-Cluster-Metrics
一个应用软件维护的后期一定是要做监控,akka也不例外,它提供了集群模式下的度量扩展插件. 其实如果读者读过前面的系列文章的话,应该是能够自己写一个这样的监控工具的.简单来说就是创建一个actor,它 ...
- 多维DP UVA 11552 Fewest Flop
题目传送门 /* 题意:将子符串分成k组,每组的字符顺序任意,问改变后的字符串最少有多少块 三维DP:可以知道,每一组的最少块是确定的,问题就在于组与组之间可能会合并块,总块数会-1. dp[i][j ...
- yii int
@echo off rem ------------------------------------------------------------- rem Yii command line ini ...
- EasyUI系列学习(十一)-Accordion(分类)
一.加载 1.class加载 <div class="easyui-accordion" style="width:300px;height:200px" ...
- ElasticSearch 安装使用
安装: 1.下载ElasticSearch.解压到相关文件夹 2.运行elasticsearch.bat,启动程序 3.在浏览器输入:http://localhost:9200/,显示相关Es内容即安 ...
- NVIDIA各个领域芯片现阶段的性能和适应范围
NVIDIA作为老牌显卡厂商,在AI领域深耕多年.功夫不负有心人,一朝AI火,NVIDIA大爆发,NVIDIA每年送给科研院所和高校的大量显卡,大力推广Physix和CUDA,终于钓了产业的大鱼. 由 ...
- 《网络管理》IP地址管理与子网划分
IP地址管理——ipmaster ipmaster是一款对IP地址进行管理的软件,使用该软件可以提高网络管理员的工作效率.在大型网络中,使用该软件可以有序且高效地实现大中小型企业网IP地址的分配和管理 ...
- [转]汇编语言:MOVSB,MOVSW,MOVSD
汇编语言:MOVSB,MOVSW,MOVSD 转自: http://blog.csdn.net/zhenyongyuan123/article/details/8364011 目前80386系列的 ...