2017-3-20 希尔排序, 递归, 01背包

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_37344790/article/details/64188734
问题描述
  给两组数,各n个。
  请调整每组数的排列顺序,使得两组数据相同下标元素对应相乘,然后相加的和最小。要求程序输出这个最小值。
  例如两组数分别为:1 3  -5和-2 4 1

  那么对应乘积取和的最小值应为:
  (-5) * 4 + 3 * (-2) + 1 * 1 = -25
输入格式
  第一个行一个数T表示数据组数。后面每组数据,先读入一个n,接下来两行每行n个数,每个数的绝对值小于等于1000。
  n<=8,T<=1000
输出格式

  一个数表示答案。

import java.util.Scanner;

public class Minimum {
	static Scanner scan = new Scanner(System.in);

	public static void main(String[] args) {
		int n = scan.nextInt();
		int[] array = new int[n];
		int i = 0;
		while (n > 0) {
			int length = scan.nextInt();
			int[] array1 = creatArray(length);
			int[] array2 = creatArray(length);
			shellSort(array1, true);
			shellSort(array2, false);
			array[i++] = getMin(array1,array2);
			n--;
		}
		for (int j = 0; j < array.length; j++){
			System.out.println(array[j]);
		}
	}

	public static int[] creatArray(int length) {
		int[] temp = new int[length];
		for (int i = 0; i < length; i++) {
			temp[i] = scan.nextInt();
		}
		return temp;
	}

	public static void shellSort(int[] array, boolean flag) {
		/**
		 * flag == true 降序 flag == false 升序
		 */
		int length = array.length;

		for (int step = length / 2; step > 0; step = step / 2) {
			int j;
			for (int i = step; i < length; i++) {
				int temp = array[i];
				for (j = i; j >= step && temp >= array[j - step] == flag; j -= step) {
					array[j] = array[j - step];
				}
				array[j] = temp;
			}
		}
	}

	public static int getMin(int[] a, int[] b) {
		int minimum = 0;
		int length = a.length;
		for (int i = 0; i < length; i++) {
			minimum += a[i] * b[i];
		}
		return minimum;
	}
}

分析:等到两个数组的最小乘积和,两个数组中 最大 乘 另一个数组最小 再相加

问题描述
  每年冬天,北大未名湖上都是滑冰的好地方。北大体育组准备了许多冰鞋,可是人太多了,每天下午收工后,常常一双冰鞋都不剩。
  每天早上,租鞋窗口都会排起长龙,假设有还鞋的m个,有需要租鞋的n个。现在的问题是,这些人有多少种排法,可以避免出现体育组没有冰鞋可租的尴尬场面。(两个同样需求的人(比如都是租鞋或都是还鞋)交换位置是同一种排法)
输入格式
  两个整数,表示m和n
输出格式
  一个整数,表示队伍的排法的方案数。
样例输入
3 2
样例输出
5
数据规模和约定
  m,n∈[0,18]
  问题分析
import java.util.Scanner;

public class Recursion {
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int m = scan.nextInt();
		int n = scan.nextInt();
		int sum = fun(m,n);
		System.out.println(sum);
	}

	public static int fun(int m, int n) {
		if (n == 0) {
			return 1;
		} else if (n > m) {
			return 0;
		} else {
			return fun(m - 1, n) + fun(m, n - 1);
		}
	}
}

分析:因为排列中第一个肯定是还鞋的,所以采用倒叙排列 
最后一个人 分两种情况 还鞋 OR 借鞋;
所以 f(m,n) = f(m-1 , n) + f(m , n-1);
为保证第一个为还鞋,且顺序排列时 还鞋 永远比 借鞋的多,所以 每次递归都应保证 m >= n , n > m 时则排列不存在返回0;
当 n = 0时,由于 (两个同样需求的人(比如都是租鞋或都是还鞋)交换位置是同一种排法)所以此时排列为一种情况;

背包问题
 输入的第一行有两个整数T(1 <= T <= 1000)和M(1 <= M <= 100),
 用一个空格隔开,T代表总共能够用来采药的时间,M代表山洞里的草药的数目。
 接下来的M行每行包括两个在1到100之间(包括1和100)的整数,分别表示采摘某株草药的时间和这株草药的价值。
import java.util.Scanner;

public class Main {
	public static void main(String args[]) {
		Scanner scan = new Scanner(System.in);

		int sumt = scan.nextInt();
		int count = scan.nextInt();
		int[] value = new int[sumt + 1];
		int[] v = new int[count + 1];
		int[] t = new int[count + 1];
		for (int i = 1; i < count + 1; i++) {
			t[i] = scan.nextInt();
			v[i] = scan.nextInt();
		}

		for (int i = 1; i < count + 1; i++) {
			for (int j = sumt; j >= t[i]; j--) {
				value[j] = max(value[j], value[j - t[i]] + v[i]);
			}
		}
		System.out.println(value[sumt]);
	}

	public static int max(int a, int b) {
		if (a > b)
			return a;
		else
			return b;
	}
}
分析:

经典dp 

0 1背包问题

猜你喜欢

转载自blog.csdn.net/m0_37344790/article/details/64188734
今日推荐