算法问题(语言不限)
一个二维坐标系,从(0,0)点出发,每次只能上下左右任意方向移动1,例如移动一步可以移动到(1,0)(0,1)(-1,0)(0,-1),问k步之后可以移动到多少个不同的位置(给出通式)?输出出来
可以倒着思考:假设第k步之后的不同位置为 f(k),f(k)是在f(k-1)基础上得到的,即f(k)最外层点是在f(k-1)最外层的点基础上出来的。那么可以得到一个关系式:f(k) = a(*)f(k-1)+b
(为什么是一次函数关系,很容易理解,拿第一步和第二步分析一下就看出来了,(*表示相乘的意思,不转义字符串就是斜体显示。看着别扭))。得到f(0)=1,f(k) = f(k-1)+b,下面解决b:
每走一步,就有4个方向,所以是b = 4(*)k,所以最后的表达式为:f(k) = f(k-1)+4(*)k,f(0) = 1,代码实现:
public static int function(int k){
if(k<0) {
System.out.println("k must be bigger than 0");
return -1;
}
if(k==0) return 1;
//非递归方法
int fk = 0;
for(int i=1;i<=k;i++){
fk = fk + 4*i;
}
return fk+1;
}
分析一下问题,起点是0.0 移动K步 ,最大范围就是 |x| + |y| <=k ;
如果k 是偶数 ,那么 |x| + |y| <=k 且 |x| + |y| 不能为奇数
如果k 是奇数 ,那么 |x| + |y| <=k 且 |x| + |y| 不能为偶数
然后输出所有符合 |x| + |y| <=k ; 且x,y属于整数的坐标点.符合上面几个条件
在这里分一下象限,只需要求出第一象限的所有坐标就行,由于置换到二,三,四象限只需要换x,y 的符号即可.
而第一象限的所有点是一个三角形
就是两个for 循环
for(i=0;i for(j=0;j if(i+j>k&&( 0&(i+j)!=(k&0) )break;
console.log(i,j);
console.log(i*-1,j);
console.log(i,j*-1);
console.log(i*-1,j*-1);
}
}
上面的有点问题,下面的ok了
分析一下问题,起点是0.0 移动K步 ,最大范围就是 |x| + |y| <=k ;
如果k 是偶数 ,那么 |x| + |y| <=k 且 |x| + |y| 不能为奇数
如果k 是奇数 ,那么 |x| + |y| <=k 且 |x| + |y| 不能为偶数
然后输出所有符合 |x| + |y| <=k ; 且x,y属于整数的坐标点.符合上面几个条件
在这里分一下象限,只需要求出第一象限的所有坐标就行,由于置换到二,三,四象限只需要换x,y 的符号即可.
而第一象限的所有点是一个三角形
就是两个for 循环
for(i=0;i<=k;i++){
for(j=0;j<=k;j++){
if(i+j>k||( 0&(i+j)!=(k&0) )break;
console.log(i,j);
console.log(i*-1,j);
console.log(i,j*-1);
console.log(i*-1,j*-1);
}
}
假设二维坐标系为整数坐标系,因为题目限定了起点(0,0),而且还限定了是K步,那么就构造一个正方形与正菱形交错的递归式。
fun(k)
{
if(0 != k)
{
输出半径为K的正菱形(◇)边角坐标
if(0 == k % 2)
{
输出边长为K的正方形(□)边角坐标
}
fun(k-1)
}
}
public static void main(String[] args) {
Set re = find(2,0,0);
System.out.println(re);
}
public static Set<String> find(int k,int x, int y){
Set<String> re = new HashSet<>();//java 中 set 会去掉重复的元素
if(k ==0){
re.add(x +","+y);
return re;
}
re.addAll(find(k-1,x+1,y));
re.addAll(find(k-1,x-1,y));
re.addAll(find(k-1,x,y+1));
re.addAll(find(k-1,x,y-1));
return re;
}
输出结果:
(奇葩语言负号在右边)
2- 0 0 ,0 ->1-,0 ->2-,0
1- 1- 0 ,0 ->1-,0 ->1-,1
1- 1 0 ,0 ->1-,0 ->1-,1
0 2- 0 ,0 ->0 ,1- ->0 ,2
0 0 0 ,0 ->1 ,0 ->0 ,0
0 2 0 ,0 ->0 ,1 ->0 ,2
1 1- 0 ,0 ->1 ,0 ->1 ,1
1 1 0 ,0 ->1 ,0 ->1 ,1
2 0 0 ,0 ->1 ,0 ->2 ,0
大家一起来吐槽一下奇葩的ABAP语言:
*在二维坐标系中某一点开始移动,每次只能横向或纵向移动1,求移动X 步之后的终点位置*
report aaa.
DATA: BEGIN OF STEPS OCCURS 0,
X TYPE i,
Y TYPE i,
WAY TYPE STRING,
END OF STEPS.
PERFORM GOSTEP USING 0 0 2 ''. " 初始坐标位置I ,初始坐标位置J,移动步数Z,初始路径STEP.
"输出终点位置
SORT STEPS BY X Y.
DELETE ADJACENT DUPLICATES FROM STEPS COMPARING X Y. "去除重复
loop at STEPS.
write: STEPS-X,steps-Y, steps-waY.
SKIP.
endloop.
FORM GOSTEP USING
value(X) type i
value(Y) type i
value(Z) TYPE N
value(STEP) TYPE STRING. "路径
DATA: X1 type I, Y1 type I,
S_X type string, S_Y type string.
IF STEP <> ''.
CONCATENATE STEP ' ->' INTO STEP.
ENDIF.
S_X = X.S_Y = Y.
CONCATENATE STEP S_X ',' S_Y INTO STEP.
IF Z = 0.
STEPS-X = X.
STEPS-Y = Y.
STEPS-WAY = STEP. "路径
append STEPS. "记录终点位置
ELSE.
Z = Z - 1 .
X1 = X + 1 .
PERFORM GOSTEP USING X1 Y Z STEP.
X1 = X - 1 .
PERFORM GOSTEP USING X1 Y Z STEP.
Y1 = Y + 1 .
PERFORM GOSTEP USING X Y1 Z STEP.
Y1 = Y - 1 .
PERFORM GOSTEP USING X Y1 Z STEP.
ENDIF.
endform.