UVAlive 5866 Robot Arm Planning 题解

15 篇文章 0 订阅
13 篇文章 0 订阅
这是一道关于机器人路径规划的问题,题意是在一个由n+1节点组成的链中,每个节点半径为10,边长为100。要求判断是否能通过旋转节点,使得最上方的节点被一个内部缩进10的矩形完全覆盖,且过程中不能出现自交。解决方案包括将矩形内缩避免自交,然后对所有节点的旋转角度进行枚举和剪枝操作。
摘要由CSDN通过智能技术生成

题目

Tri_integral Summer Training 4

题意:

有n+1的结点的链,每条边(结点圆心距)100,每个结点半径为10,每次可以旋转45°,但是不能自交。求是否通过旋转某些结点使得最上面的结点完全包含在一个矩形内。

题解:

首先矩形每条边向内缩10,这样只要最上面的点的圆心在新矩形即可。然后枚举所有节点旋转的角度,加上判断是否自交和剪枝,不会超时的。

因为时间紧,代码写的很丑,请轻拍……


//Time:22ms
//Memory:0KB
//Length:2709B
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <queue>
#include <cmath>
#include <set>
#include <algorithm>
#define EPS 1e-6
#define INF 1000000007
using namespace std;
struct _node
{
    double num;
    int ro;
    bool operator <(const _node &b) const
    {
        if(ro!=b.ro)
            return ro<b.ro;
        return num<b.num-EPS;
    }
};
int dcmp(double x)
{
    if(fabs(x)<EPS) return 0;
    return x<0? -1:1;
}
struct Point
{
    double x,y;
    Point(){}
    Point(double a,double b):x(a),y(b){}
    Point operator-(const Point &a)const{return Point(x-a.x,y-a.y);}
    void input()
    {
        scanf("%lf%lf",&x,&y);
    }
};
typedef Point Vector;
double Cross(Vector a, Vector b)
{
    return a.x*b.y-a.y*b.x;
}
bool Isinter(Point s1, Point e1,Point s2,Point e2)
{
    if(min(s1.x,e1.x)<=max(s2.x,e2.x)&&
       min(s1.y,e1.y)<=max(s2.y,e2.y)&&
       min(s2.x,e2.x)<=max(s1.x,e1.x)&&
       min(s2.y,e2.y)<=max(s1.y,e1.y)&&
       dcmp(Cross(s2-s1,e2-s1))*dcmp(Cross(s2-e1,e2-e1))<=0&&
       dcmp(Cross(s1-s2,e1-s2))*dcmp(Cross(s1-e2,e1-e2))<=0)
       return 1;
    return 0;
}
bool Isin(Point a,Point b,Point c)
{
    if(c.x>=a.x&&c.x<=b.x&&c.y>=a.y&&c.y<=b.y) return 1;
    return 0;
}
set<_node> se[10];
int n,ans;
Point ldown,rup;
double posx[11],posy[11];
const double sqrt2=sqrt(2.0)*50.0;
double dir[8][2]={{0,100},{sqrt2,sqrt2},{100,0},{sqrt2,-sqrt2},
                {0,-100},{-sqrt2,-sqrt2},{-100,0},{-sqrt2,sqrt2}};
int need[10]={0,1,2,3,4,3,2,1};
void dfs(int h,int sum,int ro,double x,double y)
{
    if(sum>ans)  return ;
    if(h==n)
    {
        if(Isin(ldown,rup,Point(x,y)))
            ans=min(ans,sum);
        return ;
    }
    _node node;
    node.num=x*10001+y;
    node.ro=sum;
    if(se[h].find(node)!=se[h].end())   return ;
    se[h].insert(node);
    posx[h]=x,posy[h]=y;
    if(h>=3)
        for(int i=h-3;i<h-2;++i)
            if(Isinter(Point(posx[h],posy[h]),Point(posx[h-1],posy[h-1]),
                       Point(posx[i],posy[i]),Point(posx[i+1],posy[i+1])))
                return ;
    for(int i=0;i<8;++i)
        if(i!=4)
        {
            int tro=(ro+i)%8;
            dfs(h+1,sum+need[i],tro,x+dir[tro][0],y+dir[tro][1]);
        }
    return ;
}
int main()
{
    //freopen("/home/moor/Code/input","r",stdin);
    int ncase,x,y;
    scanf("%d",&ncase);
    while(ncase--)
    {
        scanf("%d",&n);
        scanf("%d%d",&x,&y);
        x+=10,y+=10;
        ldown=Point(x,y);
        scanf("%d%d",&x,&y);
        x-=10,y-=10;
        rup=Point(x,y);
        for(int i=0;i<n;++i)    se[i].clear();
        ans=INF;
        dfs(0,0,0,0.0,0.0);
        printf("%d\n",ans==INF?-1:ans);
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值