【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 }

 

posted @ 2012-07-02 22:04  Amb@HDU  阅读(520)  评论(0编辑  收藏  举报