• 【UVALive 5866】 Robot Arm Planning


    题目链接

    今天做的一个题目,给你一个n截得机械臂,每节长度都是固定的100,可以绕每段的节点每次顺时针或者逆时针旋转45度。整个机械臂的下端固定在(0,0),问你最少多少次可以把顶端的半径为10的球完全移到一个给出的矩形区域中。

    这题貌似非常暴力的方法(8^10)也能过,不过那样多没意思。开始理解错题意了,以为每段是独立的,只跟每个方向的杆子数目有关了,敲了4层循环枚举枚举杆子的方向和数目,敲完发现不对,下面的节点转动,可以带动上面所有杆子都转动。这样虽然还是只跟每个方向的杆子数目有关,但是就不能分开计算累加得到转移次数了,转移的顺序也不能随便搞。想改暴搜,降不下复杂度,就只好顺着原来的想法去想。

    当每种方向的杆子个数确定之后,就可以得到最终球的位置并判断是否在矩形区域内了,目前的关键就是如何才能最快的移动出对应数量的方向。经过相当一段时间才理清楚,当从下向上去转动杆子,当转到一个方向时隔出k个杆子再转,就可以保证某个方向的个数,个数就与最后结果无关了,只与有哪些方向有关;当转动到某一个杆的时候,上面的节点的方向是依赖于当前节点的。然后根据上面的这些,转换成了一个简单的状压dp模型:八个方向,我们通过左转和右转,遍历到我们需要的方向所要的最小次数。比如说我们有五个杆,我们得到要2次向右,2次左上和1次向上,那么我们只要第1个杆不动,第2个杆左转1次,隔2个杆右转3次就可以得到了。很不错的一个题目。

    比赛时候的代码,比较挫,8ms:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cmath>
     4 #include<algorithm>
     5 using namespace std;
     6 
     7 inline int ABS(int x){return x<0?-x:x;}
     8 
     9 int dis[1<<8][10];
    10 void dfs(int end, int p){
    11     if(end==0){
    12         dis[end][p]=0;
    13         return;
    14     }
    15     //printf("= %d %d\n", end, p);
    16     //getchar();
    17     int res=-1;
    18     for(int i=0;i<8;i++){
    19         if(end&(1<<i)){
    20             if(dis[end^(1<<i)][i]==-1) dfs(end^(1<<i), i); 
    21             int tmp = dis[end^(1<<i)][i]+min((p-i+8)%8,(i-p+8)%8);
    22             if(res==-1||tmp<res) res=tmp;
    23         }
    24     }
    25     dis[end][p] = res;
    26 }
    27 
    28 int gao(int end){
    29     memset(dis, -1, sizeof(dis));
    30     int ss=end;
    31     if(end&(1<<0)) ss^=(1<<0);
    32     dfs(ss, 0);
    33     return dis[ss][0];
    34 }
    35 
    36 int clear(int a, int b, int c, int d){
    37     int end=0;
    38     if(a>0) end|=1<<0;
    39     if(c>0) end|=1<<1;
    40     if(b>0) end|=1<<2;
    41     if(d<0) end|=1<<3;
    42     if(a<0) end|=1<<4;
    43     if(c<0) end|=1<<5;
    44     if(b<0) end|=1<<6;
    45     if(d>0) end|=1<<7;    
    46     return end;
    47 }
    48 
    49 int main(){
    50     double sqrt2=sqrt(2.0);
    51     
    52     int t;
    53     scanf("%d", &t);
    54     while(t--){
    55         int n;
    56         scanf("%d", &n);
    57         double lx, ly, rx, ry;
    58         scanf("%lf%lf%lf%lf", &lx, &ly, &rx, &ry);
    59         int ans=-1;
    60         for(int a=-n;a<=n;a++){
    61         for(int b=-n;b<=n;b++){
    62         if(ABS(a)+ABS(b)>n) continue;
    63         for(int c=-n;c<=n;c++){
    64         if(ABS(a)+ABS(b)+ABS(c)>n) continue;
    65         for(int d=-n;d<=n;d++){
    66         if(ABS(a)+ABS(b)+ABS(c)+ABS(d)>n) continue;
    67         if((ABS(a)+ABS(b)+ABS(c)+ABS(d)-n)&1) continue;
    68             double posx=0;
    69             double posy=0;
    70             posx+=b*100.0+(c-d)*100.0/sqrt2;
    71             posy+=a*100.0+(c+d)*100.0/sqrt2;
    72             //printf("%lf %lf\n", posx, posy);
    73             if(posx<=rx-10&&posx>=lx+10&&posy<=ry-10&&posy>=ly+10){
    74                 int end=0;
    75                 if(n-(ABS(a)+ABS(b)+ABS(c)+ABS(d))){
    76                     for(int i=0;i<4;i++){
    77                         end=clear(a,b,c,d)|(1<<i)|(1<<(i+4));
    78                         //printf("= %d %d %d %d: %d\n", a,b,c,d, end);
    79                         int res = gao(end);
    80                         if(ans==-1||res<ans) ans=res;
    81                     }
    82                 }else{
    83                     end=clear(a,b,c,d);
    84                     //printf("%d %d %d %d: %d\n", a,b,c,d, end);
    85                     int res=gao(end);
    86                     if(ans==-1||res<ans) ans=res;
    87                 }
    88             }
    89         }
    90         }
    91         }
    92         }
    93         printf("%d\n", ans);
    94     }
    95 }
  • 相关阅读:
    Ionic Js十:加载动作
    Ionic Js九:列表操作
    Ionic Js八:头部和底部
    Ionic Js七:手势事件
    库文件
    驱动知识
    自启动总结
    学习笔记
    写脚本切换用户
    未找到arm-linux-gcc解决办法
  • 原文地址:https://www.cnblogs.com/ambition/p/UVALive_5866.html
Copyright © 2020-2023  润新知