蓝桥杯省赛夺奖冲刺营精讲二
「谈判」
题目描述
在很久很久以前,有 n 个部落居住在平原上,依次编号为 1 到 n。第 i 个部落的人数为。
有一年发生了灾荒。年轻的政治家小蓝想要说服所有部落一同应对灾荒,他能通过谈判来说服部落进行联合。
每次谈判,小蓝只能邀请两个部落参加,花费的金币数量为两个部落的人数之和,谈判的效果是两个部落联合成一个部落(人数为原来两个部落的人数之和)。
输入描述
输入的第一行包含一个整数 n,表示部落的数量。
第二行包含 n 个正整数,依次表示每个部落的人数。
其中,1≤n≤1000,1≤ti≤104
输出描述
输出一个整数,表示最小花费。
输入输出样例
示例 1
输入
4
9 1 3 5
输出
31
运行限制
最大运行时间:1s
最大运行内存: 128M
代码1
蓝桥杯官网的测试器好像有问题,我的这个代码通过了,但其实是错的,直接升序排序后,从左到右,一次谈判。
例:3 4 5 6,
(3+4)=7
(7+5)=12
(12+6)=20
ans=39
是错误的!!
import java.util.Arrays;
import java.util.Scanner;
public class Main {
static int n;
static int[] people;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n=sc.nextInt();//部落数
people=new int[n];
for (int i = 0; i < n; i++) {
people[i]=sc.nextInt();
}
Arrays.sort(people);
int ans=0;
int t=people[0];
for (int i = 1; i < n; i++) {
t=t+people[i];
ans+=t;
}
System.out.println(ans);
}
}
代码2
每次选了最小的两个谈判后,要进行排序
例:3 4 5 6,
(3+4)7
(5+6)11 //这时就在7 5 6中排序,选最小的俩
(7+11)18
ans=36
我觉得有点像哈夫曼树,生成最短编码
import java.util.Arrays;
import java.util.Scanner;
public class Main {
static int n;
static int[] people;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n=sc.nextInt();//部落数
people=new int[n];
for (int i = 0; i < n; i++) {
people[i]=sc.nextInt();
}
Arrays.sort(people);
int ans=0;
int t;
for (int i = 0; i < n-1; i++) {
t=people[i]+people[i+1];
ans+=t;
people[i+1]=t;
Arrays.sort(people,i+1,n);
}
System.out.println(ans);
}
}
「排座椅」
题目描述
上课的时候总有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情。不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来之后,只有有限的 D 对同学上课时会交头接耳。同学们在教室中坐成了 M 行 N 列,坐在第 i 行第 j 列的同学的位置是(i,j),为了方便同学们进出,在教室中设置了 K 条横向的通道,L 条纵向的通道。于是,聪明的小雪想到了一个办法,或许可以减少上课时学生交头接耳的问题:她打算重新摆放桌椅,改变同学们桌椅间通道的位置,因为如果一条通道隔开了两个会交头接耳的同学,那么他们就不会交头接耳了。
请你帮忙给小雪编写一个程序,给出最好的通道划分方案。在该方案下,上课时交头接耳的学生对数最少。
输入描述
输入第一行,有 5 各用空格隔开的整数,分别是 M,N,K,L,D(2≤N,M≤1000,0≤K<M,0≤L<N,D≤2000)。
接下来D 行,每行有 4 个用空格隔开的整数,第 i 行的 4 个整数 Xi,Yi ,Pi,Qi,表示坐在位置 (Xi,Yi) 与 (Pi ,Qi) 的两个同学会交头接耳(输入保证他们前后相邻或者左右相邻)。
输入数据保证最优方案的唯一性。
输出描述
输出共两行。
第一行包含 K 个整数,a1,a2,⋯aK,表示第a1行和a1+1 行之间、第 a2 行和第 a2+1 行之间、…、第 aK 行和第aK+1 行之间要开辟通道,其中 ai<ai+1,每两个整数之间用空格隔开(行尾没有空格)。
第二行包含 L 个整数,b1 ,b 2 ,⋯b k,表示第 b1 列和 b_1+1b 1 +1 列之间、第 b2列和第b2+1 列之间、…、第bL列和第b L +1 列之间要开辟通道,其中b i <b i +1,每两个整数之间用空格隔开(行尾没有空格)。
输入输出样例
示例 1
输入
4 5 1 2 3
4 2 4 3
2 3 3 3
2 5 2 4
输出
2
2 4
运行限制
最大运行时间:1s
最大运行内存: 128M
代码
最开始选了很多存储vector,map,数组,等,太浪费时间了!!想清楚再动手
找index的时候,每次都是选的最大的先输出,但其实不需要,按坐标由小到大就行!
import java.util.Scanner;
public class Main {
static int m,n,k,l,d;
static int[] row;//行数,这一行讲话数
static int[] col;//列数,这一列讲话数
static int[] rowIndex;//列数,这一列讲话数
static int[] colIndex;//列数,这一列讲话数
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
m=sc.nextInt();//行数
n=sc.nextInt();//列数
k=sc.nextInt();//横过道数
l=sc.nextInt();//纵过道数
d=sc.nextInt();//说话数
row=new int[m+1];
rowIndex=new int[m+1];
col=new int[n+1];
colIndex=new int[n+1];
int r1,c1,r2,c2,rowN=0,colN=0;
while(d-->0) {
r1=sc.nextInt();
c1=sc.nextInt();
r2=sc.nextInt();
c2=sc.nextInt();
int min;
if(r1==r2) {
min=Math.min(c1, c2);
col[min]+=1;
}else {
min=Math.min(r1, r2);
row[min]+=1;
}
}
int index=0;
for (int i = 0; i < k; i++) {
index=findMax(row);
rowIndex[index]=1;
}
for (int i = 0; i < l; i++) {
index=findMax(col);
colIndex[index]=1;
}
for (int i = 0; i < m+1; i++) {
if(rowIndex[i]==1)
System.out.print(i+" ");
}
System.out.println();
for (int i = 0; i < n+1; i++) {
if(colIndex[i]==1)
System.out.print(i+" ");
}
}
private static int findMax(int[] arr) {
int posi=-1;
int max=-1;
for (int i = 0; i < arr.length; i++) {
if(arr[i]>max) {
max=arr[i];
posi=i;
}
}
arr[posi]=0;
return posi;
}
}