蓝桥 最小乘积(基本型) dfs
问题描述
给两组数,各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
输出格式
一个数表示答案。
样例输入
2 3 1 3 -5 -2 4 1 5 1 2 3 4 5 1 0 1 0 1
样例输出
-25
6
思路:
对于a,b两个数组 dfs第一个数组的每个值 然后对于每一次dfs 依次循环b数组的值 使用一个值就标记表示这个值已使用 然后统计sum的最小值
还有一种做法是把两个数组排序 一个升序 一个降序 然后遍历两个数组 依次最大值*最小值就是res 但是我没想到 还是直接用暴力
1 import java.util.Scanner; 2 public class 最小乘积 { 3 static final int N=10; 4 static int m; 5 static int n; 6 static int q[]=new int[N]; //q和a数组为输入的两个数组 7 static int a[]=new int[N]; 8 static long sum; 9 static long res=Integer.MAX_VALUE; 10 static boolean vis[]=new boolean[N]; 11 public static void main(String[] args) { 12 Scanner sc=new Scanner(System.in); 13 m=sc.nextInt(); 14 while(m-->0){ 15 n=sc.nextInt(); 16 for(int i=1;i<=n;i++){ 17 q[i]=sc.nextInt(); 18 } 19 for(int i=1;i<=n;i++){ 20 a[i]=sc.nextInt(); 21 } 22 dfs(1); 23 System.out.println(res); 24 res=Integer.MAX_VALUE;//每一组数组完成 res都要重新赋为最大值 防止对下一组数据产生影响 25 } 26 } 27 static void dfs(int u){ 28 if(u>n){ 29 res=Math.min(res, sum); 30 return; 31 } 32 for(int i=1;i<=n;i++){ 33 if(!vis[i]){ //如果在b数组中这个值没有访问过 就执行 34 vis[i]=true; 35 sum += q[u]*a[i]; //使用这个值 36 dfs(u+1); 37 vis[i]=false; 38 sum -= q[u]*a[i]; 39 } 40 } 41 } 42 }