zoukankan      html  css  js  c++  java
  • POJ 1207 The 3n + 1 problem

    题目链接:http://poj.org/problem?id=1207

    题目大意:给你一个数x,规定一个函数F(x),如果x为1则F(x)==1,否则如果x是偶数,F(x)==F(x/2),x为奇数F(x)==F(3*x+1)计算给定x到变换到1的步数。

    注意点:

    1.提供的每组两个数字不一定是左边小右边大,所以可能要交换两者的值,另外,输出时必须要按两个数出现的顺序输出

    或者可以,先输出两个数,最后输出maxlen的值,保证在同一行即可

    2.直接枚举比较也是可以通过的,打表同样是可以的,因为数据范围不是很大

    3.其他的还有深搜法,记忆法什么的,参考网址:http://hi.baidu.com/wzyjerry/blog/item/f7c1e44481ced42586947347.html     深搜+记忆化

    方法一:直接枚举

    Memory: 3004K
    Time: 204MS

    import java.util.Scanner;
    
    public class Main{
    
        public static void main(String[] args) {
            Scanner sin=new Scanner(System.in);
            int start,end,len,maxlen,temp;
            while(sin.hasNext()){
                maxlen=0;
                temp=0;
                start=sin.nextInt();
                end=sin.nextInt();
                if(start>end){
                    temp=end;
                    end=start;
                    start=temp;
                }
                for(int i=start;i<=end;i++){
                    len=calculateLen(i);
                    if(len>maxlen){
                        maxlen=len;
                    }
                }
                if(temp==0){
                    System.out.println(start+" "+end+" "+(maxlen));
                }else{
                    System.out.println(end+" "+start+" "+(maxlen));
                }
            }
        }
        
        public static int calculateLen(int n){
            int len=1;
            while(n!=1){
                if(n%2==0){
                    n=n/2;
                }else{
                    n=3*n+1;
                }
                len++;
            }
            return len;
        }
    }

    方法二:打表   

    Memory: 3044K
    Time: 172MS

    import java.util.Scanner;
    
    public class Main{
        
        public static int[] lens=new int[10002];
    
        public static void main(String[] args) {
            Scanner sin=new Scanner(System.in);
            calculateLen();
            int start,end,maxlen,temp;
            while(sin.hasNext()){
                maxlen=0;
                temp=0;
                start=sin.nextInt();
                end=sin.nextInt();
                if(start>end){
                    temp=end;
                    end=start;
                    start=temp;
                }
                for(int i=start;i<=end;i++){
                    if(lens[i]>maxlen){
                        maxlen=lens[i];
                    }
                }
                if(temp==0){
                    System.out.println(start+" "+end+" "+(maxlen+1));//注意这里的括号(),不能少,不然会出现问题,将1看作了一个字符
                }else{
                    System.out.println(end+" "+start+" "+(maxlen+1));
                }
            }
        }
        
        public static void calculateLen(){
            int i,n;
            for(i=1;i<10002;i++){
                lens[i]=0;
                n=i;
                while(n!=1){
                    if(n%2==0){
                        n=n/2;
                    }else{
                        n=3*n+1;
                    }
                    lens[i]++;
                }
            }
        }
    }
    

    方法三:深搜+记忆优化

    Memory: 1024K
    Time: 0MS

    #include <iostream>
    #include <string.h>
    using namespace std;
    int M[200001];
    int Ans;
    int dfs(int n)
    {
        if(n==1)
            return 1;
        if(n>200000)
        {
            if(n%2==0)
                return dfs(n/2)+1;//这里就是深搜,此处向下递归了一层,后面加上 1
            else
                return dfs(n*3+1)+1;
        }
        if(!M[n])//判断是否已经求过n的长度,如果没有的话就去求,否则直接返回上次求得的值[记忆]
        {
            if(n%2==0)
                return M[n]=dfs(n/2)+1;
            else
                return M[n]=dfs(n*3+1)+1;
        }
        else
            return M[n];
    }
    int main()
    {
        int a,b;
        M[0]=1;
        for(int i=1; i<=10000; i++)
        {
            M[i]=dfs(i);//这里实际上就是打表,但是它主要的目的是保存那些频繁计算的数的长度
        }
        while(cin >> a >> b)
        {
            cout << a << ' ' << b << ' ';
            Ans=0;
            for(int i=min(a,b); i<=max(a,b); i++)
                Ans=max(Ans,M[i]);
            cout << Ans << endl;
        }
        return 0;
    }
    
     
  • 相关阅读:
    要发布游戏啦,平台要 3000个6位不重复的验证码 看我怎么做!!!
    数字化婚姻配对尝试
    java 和 .NET 的 类继承方面 的不同
    Asp.Net Core 实现谷歌翻译ApI 免费版
    Asp.Net Core 全局模型验证
    Asp.Net Core 下 Newtonsoft.Json 转换字符串 null 替换成string.Empty
    Windows 10 远程连接出现函数错误 【这可能由于CredSSP加密Oracle修正】
    矫正系统时间
    linux 安装WildFly 及可能遇到的问题
    ubuntu 安装 jdk-7
  • 原文地址:https://www.cnblogs.com/yinger/p/2107761.html
Copyright © 2011-2022 走看看