链接:
https://www.nowcoder.com/acm/contest/106/J
来源:牛客网
Various Tree
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
64bit IO Format: %lld
题目描述
It’s universally acknowledged that there’re innumerable trees in the campus of HUST.
And there are many different types of trees in HUST, each of which has a number represent its type. The doctors of biology in HUST find 4 different ways to change the tree’s type x into a new type y:
1. y=x+1
2. y=x-1
3. y=x+f(x)
4. y=x-f(x)
The function f(x) is defined as the number of 1 in x in binary representation. For example, f(1)=1, f(2)=1, f(3)=2, f(10)=2.
Now the doctors are given a tree of the type A. The doctors want to change its type into B. Because each step will cost a huge amount of money, you need to help them figure out the minimum steps to change the type of the tree into B.
Remember the type number should always be a natural number (0 included).
输入描述:
One line with two integers A and B, the init type and the target type.
输出描述:
You need to print a integer representing the minimum steps.
题意:给定两个正整数A,B和四种变化方式y=x+1,y=x-1,y=x+f(x),y=x-f(x).其中f(x)的定义为x转化为二进制数后其中1的个数,然后求将A变为B最少需要几次操作。
题解:一开始觉得是贪心,然后发现贪心的时候总是不能保证最优,而且还存在时间复杂度的问题。但是贪心的时候想到的一个条件启发了我,先到达的点一定是最优的,那么是不是就Di算法求最短路很像呢,然后顺着思路想下去,发现其实可以用bfs求A到B的最短路,移动方式一共有四种,所以就是隐藏了一个图。时间复杂度为O(n)
代码:
import java.util.Scanner;
import java.util.LinkedList;
import java.util.Queue;
public class Main {
private final static int maxn = 1000025;
private static int [] ans = new int[maxn];
public void init(){
for(int i=0; i<maxn; i++){
ans[i] = -1;
}
}
public int f(int k){
int counter = 0;
while(k != 0){
if((k&1) == 1){
counter++;
}
k >>= 1;
}
return counter;
}
public void bfs(int k, int y){
Queue<Integer> q = new LinkedList<Integer>();
q.add(k);
int deep = 1;
while(!q.isEmpty()){
int length = q.size();
for(int i=0; i<length; i++){
int x = q.poll(), t = f(x);
if(x+1<maxn && ans[x+1] == -1){
ans[x+1] = deep;
q.add(x+1);
}
if(x-1>=0 && ans[x-1] == -1){
ans[x-1] = deep;
q.add(x-1);
}
if(x+t<maxn+20 && ans[x+t] == -1){
ans[x+t] = deep;
q.add(x+t);
}
if(x-t>=0 && ans[x-t] == -1){
ans[x-t] = deep;
q.add(x-t);
}
}
deep++;
if(ans[y] != -1)
return;
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int a = in.nextInt();
int b = in.nextInt();
Main m = new Main();
m.init();
ans[a] = 0;
m.bfs(a, b);
System.out.println(ans[b]);
in.close();
}
}
有些题可能用一些看起来没什么关系的算法求解,取决自己的建模能力和算法理解深度了,感觉这个bfs还是考的很好的。