【UVALive 5866】 Robot Arm Planning
2012-07-02 22:04
375 查看
题目链接
今天做的一个题目,给你一个n截得机械臂,每节长度都是固定的100,可以绕每段的节点每次顺时针或者逆时针旋转45度。整个机械臂的下端固定在(0,0),问你最少多少次可以把顶端的半径为10的球完全移到一个给出的矩形区域中。
这题貌似非常暴力的方法(8^10)也能过,不过那样多没意思。开始理解错题意了,以为每段是独立的,只跟每个方向的杆子数目有关了,敲了4层循环枚举枚举杆子的方向和数目,敲完发现不对,下面的节点转动,可以带动上面所有杆子都转动。这样虽然还是只跟每个方向的杆子数目有关,但是就不能分开计算累加得到转移次数了,转移的顺序也不能随便搞。想改暴搜,降不下复杂度,就只好顺着原来的想法去想。
当每种方向的杆子个数确定之后,就可以得到最终球的位置并判断是否在矩形区域内了,目前的关键就是如何才能最快的移动出对应数量的方向。经过相当一段时间才理清楚,当从下向上去转动杆子,当转到一个方向时隔出k个杆子再转,就可以保证某个方向的个数,个数就与最后结果无关了,只与有哪些方向有关;当转动到某一个杆的时候,上面的节点的方向是依赖于当前节点的。然后根据上面的这些,转换成了一个简单的状压dp模型:八个方向,我们通过左转和右转,遍历到我们需要的方向所要的最小次数。比如说我们有五个杆,我们得到要2次向右,2次左上和1次向上,那么我们只要第1个杆不动,第2个杆左转1次,隔2个杆右转3次就可以得到了。很不错的一个题目。
比赛时候的代码,比较挫,8ms:
今天做的一个题目,给你一个n截得机械臂,每节长度都是固定的100,可以绕每段的节点每次顺时针或者逆时针旋转45度。整个机械臂的下端固定在(0,0),问你最少多少次可以把顶端的半径为10的球完全移到一个给出的矩形区域中。
这题貌似非常暴力的方法(8^10)也能过,不过那样多没意思。开始理解错题意了,以为每段是独立的,只跟每个方向的杆子数目有关了,敲了4层循环枚举枚举杆子的方向和数目,敲完发现不对,下面的节点转动,可以带动上面所有杆子都转动。这样虽然还是只跟每个方向的杆子数目有关,但是就不能分开计算累加得到转移次数了,转移的顺序也不能随便搞。想改暴搜,降不下复杂度,就只好顺着原来的想法去想。
当每种方向的杆子个数确定之后,就可以得到最终球的位置并判断是否在矩形区域内了,目前的关键就是如何才能最快的移动出对应数量的方向。经过相当一段时间才理清楚,当从下向上去转动杆子,当转到一个方向时隔出k个杆子再转,就可以保证某个方向的个数,个数就与最后结果无关了,只与有哪些方向有关;当转动到某一个杆的时候,上面的节点的方向是依赖于当前节点的。然后根据上面的这些,转换成了一个简单的状压dp模型:八个方向,我们通过左转和右转,遍历到我们需要的方向所要的最小次数。比如说我们有五个杆,我们得到要2次向右,2次左上和1次向上,那么我们只要第1个杆不动,第2个杆左转1次,隔2个杆右转3次就可以得到了。很不错的一个题目。
比赛时候的代码,比较挫,8ms:
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; inline int ABS(int x){return x<0?-x:x;} int dis[1<<8][10]; void dfs(int end, int p){ if(end==0){ dis[end][p]=0; return; } //printf("= %d %d\n", end, p); //getchar(); int res=-1; for(int i=0;i<8;i++){ if(end&(1<<i)){ if(dis[end^(1<<i)][i]==-1) dfs(end^(1<<i), i); int tmp = dis[end^(1<<i)][i]+min((p-i+8)%8,(i-p+8)%8); if(res==-1||tmp<res) res=tmp; } } dis[end][p] = res; } int gao(int end){ memset(dis, -1, sizeof(dis)); int ss=end; if(end&(1<<0)) ss^=(1<<0); dfs(ss, 0); return dis[ss][0]; } int clear(int a, int b, int c, int d){ int end=0; if(a>0) end|=1<<0; if(c>0) end|=1<<1; if(b>0) end|=1<<2; if(d<0) end|=1<<3; if(a<0) end|=1<<4; if(c<0) end|=1<<5; if(b<0) end|=1<<6; if(d>0) end|=1<<7; return end; } int main(){ double sqrt2=sqrt(2.0); int t; scanf("%d", &t); while(t--){ int n; scanf("%d", &n); double lx, ly, rx, ry; scanf("%lf%lf%lf%lf", &lx, &ly, &rx, &ry); int ans=-1; for(int a=-n;a<=n;a++){ for(int b=-n;b<=n;b++){ if(ABS(a)+ABS(b)>n) continue; for(int c=-n;c<=n;c++){ if(ABS(a)+ABS(b)+ABS(c)>n) continue; for(int d=-n;d<=n;d++){ if(ABS(a)+ABS(b)+ABS(c)+ABS(d)>n) continue; if((ABS(a)+ABS(b)+ABS(c)+ABS(d)-n)&1) continue; double posx=0; double posy=0; posx+=b*100.0+(c-d)*100.0/sqrt2; posy+=a*100.0+(c+d)*100.0/sqrt2; //printf("%lf %lf\n", posx, posy); if(posx<=rx-10&&posx>=lx+10&&posy<=ry-10&&posy>=ly+10){ int end=0; if(n-(ABS(a)+ABS(b)+ABS(c)+ABS(d))){ for(int i=0;i<4;i++){ end=clear(a,b,c,d)|(1<<i)|(1<<(i+4)); //printf("= %d %d %d %d: %d\n", a,b,c,d, end); int res = gao(end); if(ans==-1||res<ans) ans=res; } }else{ end=clear(a,b,c,d); //printf("%d %d %d %d: %d\n", a,b,c,d, end); int res=gao(end); if(ans==-1||res<ans) ans=res; } } } } } } printf("%d\n", ans); } }
相关文章推荐
- UVAlive 5866 Robot Arm Planning 题解
- bfs UVA 12569 - Planning mobile robot on Tree (EASY Version)
- Robot Race UVALive - 7020几何暴力
- UVA-12569 Planning mobile robot on Tree (EASY Version) (BFS+状态压缩)
- UVa 12569 Planning mobile robot on Tree
- Maze For Robot - UVaLive 4040 dp
- UVa 12569:Planning mobile robot on Tree(EASY Version)(BFS)
- BNU 0821 F. Robot Arm Planning
- UVa 12569 - Planning mobile robot on Tree (EASY Version)(BFS+状态压缩)
- UVA Planning mobile robot on Tree树上的机器人(状态压缩+bfs)
- UVa 12569 - Planning mobile robot on Tree (EASY Version)
- UVALive 6916---Punching Robot(卢卡斯+容斥)
- UVALive - 6916 Punching Robot Lucas+dp
- UVALive 4261——Trip Planning——————【dp+打印路径】
- Planning mobile robot on Tree (EASY Version) UVA - 12569
- UVALive 4262——Trip Planning——————【Tarjan 求强连通分量个数】
- UVALive 7608 Robot(模拟)
- Robot Race UVALive - 7020(几何数学 判断钝角)
- UVALive 6694 - Toy Boxes(思维+二分)
- UVALive - 4080 Warfare And Logistics