您的位置:首页 > 其它

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

#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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: