版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_37344790/article/details/64188734
问题描述
给两组数,各n个。
请调整每组数的排列顺序,使得两组数据相同下标元素对应相乘,然后相加的和最小。要求程序输出这个最小值。
例如两组数分别为:1 3 -5和-2 4 1
那么对应乘积取和的最小值应为:
(-5) * 4 + 3 * (-2) + 1 * 1 = -25
请调整每组数的排列顺序,使得两组数据相同下标元素对应相乘,然后相加的和最小。要求程序输出这个最小值。
例如两组数分别为:1 3 -5和-2 4 1
那么对应乘积取和的最小值应为:
(-5) * 4 + 3 * (-2) + 1 * 1 = -25
输入格式
第一个行一个数T表示数据组数。后面每组数据,先读入一个n,接下来两行每行n个数,每个数的绝对值小于等于1000。
n<=8,T<=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个。现在的问题是,这些人有多少种排法,可以避免出现体育组没有冰鞋可租的尴尬场面。(两个同样需求的人(比如都是租鞋或都是还鞋)交换位置是同一种排法)
输入格式
两个整数,表示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背包问题