zoukankan      html  css  js  c++  java
  • [迭代加深]Addition Chains

    友情♂链接

    题目大意

    已知一个数列,其中(a_1=0,a_m=n,a_1<a_2<a_3....<a_m)对于每一个k,满足a_k = a_i + a_j,i,j可相等。

    给定n(<=100),输出最小m的数列。

    样例输入

    5
    7
    12
    15
    77
    0

    样例输出

    1 2 4 5
    1 2 4 6 7
    1 2 4 8 12
    1 2 4 5 10 15
    1 2 4 8 9 17 34 68 77

    解题思路

    首先,数据并不很大,看起来是可以暴力出奇迹的。

    然而题目数据多,并且一些特殊的数据,即便题目数据并不大也会很慢。

    因此我们需要进行优化。

    它要让我们输出最小的m的数列,其实也就是明摆着告诉我们去从小到大枚举m,这样我们就可以完成了。

    对于一个数,m是一定会有下限的。其下限其实就是最大的2的k次方小于n。

    至于为什么是这样,我们所构造的数列其实就是a[i] = a[i - 1] * 2。又是升序排列,一定最大。

    但这样并不能过。

    我们还需优化,请看下面这一段代码

    for (int i = dep - 1;i >= 1;i --){
    		for (int j = i;j >= 1;j --){
    			/*if (a[inde][i] + a[inde][j] < a[inde][dep - 1])
    				continue;*/
    			/*int sum = a[inde][i] + a[inde][j];
    			for (int k = dep + 2;k <= max_dep; k ++)
    				sum *=2;
    			if (sum < inde)
    				return ;*/
    			a[inde][dep] = a[inde][i] + a[inde][j];
    			dfs(inde,dep + 1,max_dep);
    			if (flag == 1)
    				return ;
    		}
    	}

    注释的便是优化代码

    第一个其实就是判断合不合格,数列要求升虚。大家别小看这一个优化,这真的是非常有用的剪枝,有这一个就可以A了。然而当时做也就只会暴力了。

    第二个优化其实就是一个判断,也就是后面全部取最大,但都达不过要求的值,我们就不用在进行遍历。

    不得不说还是比较水。

    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    #include<queue>
    #include<cstdlib>
    using namespace std;
    int n,a[1005][30];
    bool flag ;
    void dfs(int inde,int dep,int max_dep){
    	if (a[inde][dep - 1] == inde){
    		a[inde][0] = dep - 1;
    		flag = 1;
    		return ;
    	}
    	if (max_dep < dep || a[inde][dep - 1] > inde)
    		return ;
    	for (int i = dep - 1;i >= 1;i --){
    		for (int j = i;j >= 1;j --){
    			/*if (a[inde][i] + a[inde][j] < a[inde][dep - 1])
    				continue;*/
    			/*int sum = a[inde][i] + a[inde][j];
    			for (int k = dep + 2;k <= max_dep; k ++)
    				sum *=2;
    			if (sum < inde)
    				return ;*/
    			a[inde][dep] = a[inde][i] + a[inde][j];
    			dfs(inde,dep + 1,max_dep);
    			if (flag == 1)
    				return ;
    		}
    	}
    }
    int solve(int xx){
    	int t = 1,tot = 1;
    	while (t < xx){
    		tot ++;
    		t *= 2;
    	}
    	return tot;
    }
    int main(){
    	for (int ii = 2;ii <= 100;ii ++){
    		flag = 0;
    		a[ii][1] = 1;
    		int j = solve(ii);
    		for (;;j ++){
    			dfs(ii,2,j);
    			if (flag == 1)
    				break;
    		}
    	}
    	while (scanf ("%d",&n)){
    		flag = 0;
    		if (n == 0)
    			return 0;
    		if (n == 1){
    			printf("1
    ");
    			continue;
    		}
    		for (int i = 1;i < a[n][0];i ++)
    			printf("%d ",a[n][i]);
    		printf("%d
    ",a[n][a[n][0]]);
    	}
    }

    考试的时候心灰意冷,决定打表....毕竟n只有100,然而最后放弃了

  • 相关阅读:
    设计模式
    《黑马程序员》类和对象(Objective
    《黑马程序员》认识OC的第一个程序(Objective-c)
    《黑马程序员》 字符串 (C语言)
    《黑马程序员》 关键字---typedef (C语言)
    《黑马程序员》预处理指令(宏定义、条件编译、文件包含)(C语言)
    《黑马程序员》 结构体struct (C语言)
    《黑马程序员》局部变量与全局变量 (C语言)
    《黑马程序员》 ★指针练习★ (C语言)
    《黑马程序验》数组与函数(C语言)
  • 原文地址:https://www.cnblogs.com/lover-fucker/p/13566680.html
Copyright © 2011-2022 走看看