https://vjudge.net/problem/UVA-503

题目

给出一个长方体和长方体上两点的坐标,求两点的沿着长方体表面走的最小距离

题解

沿着表面走就是在展开图上面走,如果分类讨论就需要考虑很多情况,比如两个相邻的面、相对的面,有时候需要走4个展开面,有时候要走3个,是不是走的面越多距离越长,这些都说不清楚……而且手动写出所有情况很麻烦……

于是只有选择模拟展开这个长方体了,需要考虑很多细节,比如给面编号,把每个点对应到面的坐标找出来,然后还要判断走展开图是否不会超出每个面

这时我写过的最长的模拟了……

AC代码

#include<cstdio>
#include<cmath>
#include<cctype>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cassert>
#include<map>
#include<string>
using namespace std;
#define REP(r,x,y) for(register int r=(x); r<y; r++)
#define REPE(r,x,y) for(register int r=(x); r<=y; r++)
#ifdef sahdsg
#define DBG(...) printf(__VA_ARGS__)
#else
#define DBG(...) (void)0
#endif #define MAXN 10007
int l,w,h;
inline int calc(int a, int b) {return a*a+b*b;}
inline int tabs(int x) {return x<0?-x:x;}
#define LL long long
template <class T, int z>
struct A{
T data[z];
int n;
A():n(0) {}
T& operator[](int q) {return data[q];}
inline void push(T x) {data[n++]=x;}
inline T& pop() {return data[--n];}
};
#define EPS 1e-6
inline int dcmp(double x) {return fabs(x)<EPS?0:(x<0?-1:1);}
#define D Point
#define CD const D
struct Point {
double x,y;
};
struct Box {
int x,y,w,h;
};
D operator-(CD&l, CD&r) {return (D){l.x-r.x,l.y-r.y};}
D operator+(CD&l, CD&r) {return (D){l.x+r.x,l.y+r.y};}
D operator*(CD&l, double r) {return (D){l.x*r, l.y*r};}
bool operator<(CD&l, CD&r) {
return dcmp(l.x-r.x)<0 ||
(dcmp(l.x-r.x)==0 && dcmp(l.y-r.y)<0);
}
double cross(CD&l, CD&r) {return l.x*r.y-l.y*r.x;}
double dot(CD&l, CD&r) {return l.x*r.x+l.y*r.y;}
bool onseg(CD&p, CD&a, CD&b) {
return dcmp(cross(a-p,b-p))==0&&dcmp(dot(a-p,b-p))<0;
}
bool segsec(CD&a, CD&b, CD&c, CD&d) {
if(onseg(a,c,d) || onseg(b,c,d) || onseg(c,a,b) || onseg(d,a,b)) return 1;
double c1=cross(b-a,c-a), c2=cross(b-a,d-a), c3=cross(d-c,a-c), c4=cross(d-c,b-c);
return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
}
D intersec (CD&a, CD&b, CD&c, CD&d) {
D v=b-a,w=d-c,u=a-c;
double t=cross(w,u)/cross(v,w);
return a+v*t;
}
bool inbox(D p, Box&r) {
p.x-=r.x,p.y-=r.y;
return dcmp(p.x)>=0 && dcmp(p.x-r.w)<=0 && dcmp(p.y)>=0 && dcmp(p.y-r.h)<=0;
}
#undef D
#undef CD
inline int id(int x, int y, int z) {
if(x==l) return 0;
if(y==0) return 1;
if(y==w) return 2;
if(z==h) return 3;
if(z==0) return 4;
//if(x==0) ans=5;
return 5;
}
struct P {
int x,y,z;
int id;
int dx,dy;
} p,q;
const int way[6][6]={
{0,1,2,3,4,5}, {1,5,0,3,4,2}, {2,0,5,3,4,1}, {3,1,2,5,0,4}, {4,1,2,0,5,3}, {5,2,1,3,4,0}
};
const int *len[6][4]={
{&h,&h,&w,&w}, {&h,&h,&l,&l}, {&h,&h,&l,&l}, {&l,&l,&w,&w}, {&l,&l,&w,&w}, {&h,&h,&w,&w}
};
inline void task1(int x,int y, int z, int id, int&dx, int &dy) {
switch(id) {
case 0: dx=y,dy=h-z;break;
case 1: dx=x,dy=h-z;break;
case 2: dx=l-x,dy=h-z;break;
case 3: dx=y,dy=x;break;
case 4: dx=y,dy=l-x;break;
case 5: dx=w-y,dy=h-z;break;
}
}
bool vis[6];
A<int,6> op;
int oid[6];
const int _1[]={1,5,0,3,4,2};
const int _2[]={2,0,5,3,4,1};
const int _3[]={3,1,2,5,0,4};
const int _4[]={4,1,2,0,5,3};
inline void rotateO(int x) {
int ooid[6];
switch(x) {
case 1: REP(i,0,6) ooid[i]=oid[_1[i]];break;
case 2: REP(i,0,6) ooid[i]=oid[_2[i]];break;
case 3: REP(i,0,6) ooid[i]=oid[_3[i]];break;
case 4: REP(i,0,6) ooid[i]=oid[_4[i]];break;
default: assert(false);
}
memcpy(oid,ooid,sizeof oid);
}
const int fan[]={0 ,2,1,4,3};
bool findp() {
if(oid[0]==p.id) return true;
vis[oid[0]]=1;
REPE(i,1,4) if(!vis[oid[i]]) {
op.push(i); rotateO(i);
if(findp()) return true;
op.n--; rotateO(fan[i]);
}
vis[oid[0]]=0;
return false;
}
void dop();
void findq(int op1, int op2) {
if(oid[0]==q.id) {dop(); return;}
vis[oid[0]]=1;
if(!vis[oid[op1]]) {
op.push(op1); rotateO(op1);
findq(op1,op2);
op.n--; rotateO(fan[op1]);
}
if(!vis[oid[op2]]) {
op.push(op2); rotateO(op2);
findq(op1,op2);
op.n--; rotateO(fan[op2]);
}
vis[oid[0]]=0;
}
inline void turnleft(int &x,int &y,int id) {
int nx, ny; nx=y,ny=(*len[id][3-1])-x;
x=nx,y=ny;
}
inline void turnright(int &x, int &y, int id) {
int nx, ny; ny=x, nx=(*len[id][1-1])-y;
x=nx,y=ny;
}
inline void turn180(int &x, int &y, int id) {
int nx, ny; nx=(*len[id][3-1])-x, ny=(*len[id][1-1])-y;
x=nx,y=ny;
}
inline void rotateP(P&x,int z) {
const int _[]={1,5,2,0};
const int Z[]={3,5,4,0};
switch(z) {
case 1:
case 2:
if(z==1) {
if(x.id==3) {turnleft(x.dx,x.dy,x.id);}
if(x.id==4) {turnright(x.dx,x.dy,x.id);}
x.id=_2[x.id];
}
if(z==2) {
if(x.id==3) {turnright(x.dx,x.dy,x.id);}
if(x.id==4) {turnleft(x.dx,x.dy,x.id);}
x.id=_1[x.id];
} break;
case 3:
case 4:
if(z==3) {
if(x.id==1) {turnright(x.dx,x.dy,x.id);}
if(x.id==2) {turnleft(x.dx,x.dy,x.id);}
if(x.id==4) {turn180(x.dx,x.dy,x.id);}
if(x.id==5) {turn180(x.dx,x.dy,x.id);}
x.id=_4[x.id];
}
if(z==4) {
if(x.id==1) {turnleft(x.dx,x.dy,x.id);}
if(x.id==2) {turnright(x.dx,x.dy,x.id);}
if(x.id==3) {turn180(x.dx,x.dy,x.id);}
if(x.id==5) {turn180(x.dx,x.dy,x.id);}
x.id=_3[x.id];
}
break;
default:
assert(false);
}
}
inline void rotate(int x) {
const int q[]={1,5,2,0};
const int k[]={0,3,5,4};
switch(x) {
case 1:
case 2:
swap(l,w);
break;
case 3:
case 4:
swap(h,l);
break;
default:
assert(false);
}
}
inline void gop() {
REP(i,0,op.n) {
rotateP(p,op[i]); rotateP(q,op[i]);
rotate(op[i]);
}
assert(p.id==0);
}
int ans;
inline void work() {
ans=0x7f7f7f7f;
p.id=id(p.x,p.y,p.z), q.id=id(q.x,q.y,q.z);
task1(p.x,p.y,p.z,p.id,p.dx,p.dy); task1(q.x,q.y,q.z,q.id,q.dx,q.dy);
REP(i,0,6) oid[i]=i;
memset(vis,0,sizeof vis); op.n=0; findp();
gop();
REP(i,0,6) oid[i]=i;
memset(vis,0,sizeof vis); op.n=0; findq(1,3);
memset(vis,0,sizeof vis); op.n=0; findq(2,3);
memset(vis,0,sizeof vis); op.n=0; findq(1,4);
memset(vis,0,sizeof vis); op.n=0; findq(2,4);
printf("%d\n", ans);
}
inline void dop() {
int nowx=0, nowy=0; int ll=l, ww=w, hh=h;
P pp,qq; pp=p,qq=q;
A<int,17> px,py;
A<Point,34> pt;
A<Box,17> pb;
px.push(0), py.push(0);
px.push(*len[0][2-1]), py.push(*len[0][4-1]);
REP(i,0,op.n) {
pb.push((Box){nowx,nowy,*len[0][3-1],*len[0][1-1]});
switch(op[i]) {
case 1:
nowx-=l; px.push(nowx);
break;
case 2:
nowx+=w; px.push(nowx);
break;
case 3:
nowy-=l;py.push(nowy);
break;
case 4:
nowy+=h; py.push(nowy);
break;
default:
assert(false);
}
rotateP(q,op[i]);rotate(op[i]);
}
pb.push((Box){nowx,nowy,*len[0][3-1],*len[0][1-1]});
q.dx+=nowx,q.dy+=nowy;
Point A=(Point){(double)p.dx,(double)p.dy}, B=(Point){(double)q.dx,(double)q.dy};
sort(px.data,px.data+px.n); sort(py.data,py.data+py.n);
pt.push(A); pt.push(B);
REP(i,0,px.n) {
Point D=intersec(A,B,(Point){(double)px[i],0},(Point){(double)px[i],1});
if(onseg(D,A,B)) pt.push(D);
}
REP(i,0,py.n) {
Point D=intersec(A,B,(Point){0,(double)py[i]},(Point){1,(double)py[i]});
if(onseg(D,A,B)) pt.push(D);
}
sort(pt.data,pt.data+pt.n);
REP(i,1,pt.n) {
bool ac=false;
REP(j,0,pb.n){
Point x=(pt[i]+pt[i-1])*0.5; if(inbox((pt[i]+pt[i-1])*0.5,pb[j])) {
ac=true; break;
}
}
if(!ac) {goto _end;}
}
ans=min(ans,(p.dx-q.dx)*(p.dx-q.dx)+(p.dy-q.dy)*(p.dy-q.dy));
assert(0==q.id);
_end:
p=pp,q=qq,l=ll,w=ww,h=hh;
} int main() {
int cnt=0;
#ifdef sahdsg
freopen("in.txt","r",stdin);
#endif // sahdsg
while(~scanf("%d%d%d%d%d%d%d%d%d",&l,&w,&h,&p.x,&p.y,&p.z,&q.x,&q.y,&q.z)) {
work();
}
return 0;
}

UVA 503 Parallelepiped walk的更多相关文章

  1. UVa 10917 A Walk Through the Forest

    A Walk Through the Forest Time Limit:1000MS  Memory Limit:65536K Total Submit:48 Accepted:15 Descrip ...

  2. uva 10596 - Morning Walk

    Problem H Morning Walk Time Limit 3 Seconds Kamal is a Motashota guy. He has got a new job in Chitta ...

  3. UVA 10196 Morning Walk(欧拉回路)

    Problem H Morning Walk Time Limit 3 Seconds Kamalis a Motashotaguy. He has got a new job in Chittago ...

  4. Uva 10596 - Morning Walk 欧拉回路基础水题 并查集实现

    题目给出图,要求判断不能一遍走完所有边,也就是无向图,题目分类是分欧拉回路,但其实只要判断度数就行了. 一开始以为只要判断度数就可以了,交了一发WA了.听别人说要先判断是否是联通图,于是用并查集并一起 ...

  5. UVa 10596 Moring Walk【欧拉回路】

    题意:给出n个点,m条路,问能否走完m条路. 自己做的时候= =三下两下用并查集做了交,WA了一发-后来又WA了好几发--(而且也是判断了连通性的啊) 搜了题解= = 发现是这样的: 因为只要求走完所 ...

  6. 狗狗40题~ (Volume C)

    A - Triangles 记忆化搜索呗.搜索以某三角形为顶的最大面积,注意边界情况. #include <stdio.h> #include <cstring> #inclu ...

  7. UVA - 10917 - Walk Through the Forest(最短路+记忆化搜索)

    Problem    UVA - 10917 - Walk Through the Forest Time Limit: 3000 mSec Problem Description Jimmy exp ...

  8. UVA 10917 Walk Through the Forest SPFA

    uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem= ...

  9. UVA 10917 Walk Through the Forest(dijkstra+DAG上的dp)

    用新模板阿姨了一天,换成原来的一遍就ac了= = 题意很重要..最关键的一句话是说:若走A->B这条边,必然是d[B]<d[A],d[]数组保存的是各点到终点的最短路. 所以先做dij,由 ...

随机推荐

  1. DataGridView自动保存列的宽度和位置

    WinForm程序中表单的自动保存列的宽度和位置,是一种常见的功能,对于用户体验来说是非常好的.现记录一下实现过程: 1.新建一个类,命为为:DataGridViewColumnStyle. 这个类实 ...

  2. Linux汇总

    Linux介绍以及VMware和Centos的安装 linux-VMtools安装 linux-创建/使用快照/克隆(类似windows中备份还原) linux目录结构 linux指令大全(归类整理) ...

  3. Create a Report in Visual Studio 在Visual Studio中创建报表

    In this lesson, you will learn how to create reports in the integrated reporting system. This system ...

  4. Spring 框架下的 JDBC

    Spring JDBC Spring 对JDBC技术规范做了进一步封装,它又叫Spring JDBCTemplate(jdbc模板技术) 纯JDBC:代码清晰的.效率最高.代码是最烦的.    Spr ...

  5. c#使用CefSharp开发winform——环境搭建

    因为nuget在线下载有时候很慢,所以下载nuget包,进行本地安装 登陆nuget官网https://www.nuget.org/下载相关资源 选择对应版本进行下载,同时需要下载相关依赖的包 ​ 最 ...

  6. zabbix获取一周内各个等级告警的次数

    # encoding:UTF-8 import xlsxwriter import datetime import pymysql import numpy as np import pandas _ ...

  7. 从0系统学Android--3.7 聊天界面编写

    从0系统学Android--3.7 聊天界面编写 本系列文章目录:更多精品文章分类 本系列持续更新中.... 3.7 编写界面的最佳实践 前面学习了那么多 UI 开发的知识,下面来进行实践,做一个美观 ...

  8. QT--动态人流量监测系统

    QT--动态人流量监测系统 简介: 本项目使用了百度AI的动态人流量监测api,以人体头肩为主要识别目标,适用于低空俯拍,出入口场景,可用于统计当前图像的锁定人数和经过的人数 项目功能 本项目分为相机 ...

  9. C#&.Net干货分享- 构建PrinterHelper直接调用打印机相关操作

    namespace Frame.Printer{    /// <summary>    ///     /// </summary>    public class Prin ...

  10. Codeforces 547C/548E - Mike and Foam 题解

    目录 Codeforces 547C/548E - Mike and Foam 题解 前置芝士 - 容斥原理 题意 想法(口胡) 做法 程序 感谢 Codeforces 547C/548E - Mik ...