太菜了,暴力解法的结果居然不对…
后来写的,下面的代码没有经过OJ,思路应该是对的。
1.平行四边形构造
给出n个值,选出4个值组成面积最大得平行四边形。
输入:
5
3 3 4 4 5
输出:
12
思路:
要组成平行四边形,至少要有两组相同的值,例如2 2 3 3。
先把输入N个数的数组排序,然后找出出现过两次且最大的两个数,进行乘积。
import java.util.Arrays;
import java.util.Scanner;
/**
* @author liu
* @Description
*/
public class Main2 {
public static void main(String[] args) {
//输入N
Scanner ss1 = new Scanner(System.in);
int N = ss1.nextInt();
//连续输入N个数,存入数组
int[] a=new int[N];
for (int i=0;i<N;i++) {
a[i] = ss1.nextInt();
}
//排序+遍历
System.out.println(fun(a));
}
//排序后找出重复且最大的两个数
private static int fun(int[] arr) {
Arrays.sort(arr);
int i = 0;
int max = 1;//面积
//找出出现过两次且最大的两个数
for (int j = arr.length - 1; j >= 1; j--) {
if (arr[j] == arr[j - 1]) {
max = max * arr[j];
j = j - 1;
i++;
if (i == 2) break;
}
}
if (i < 2) {
return 0;//出现次数为2次的数少于2,不能构成平行四边形
} else {
return max;
}
}
}
2.排序次数
有一种算法定义如下,该算法每次只能把一个元素提到序列的开头,例如2,1,3,4,只需要一次就可以把原序列从小到大有序。
现在给定乱序1-n的排列,请你计算最少需要多少次操作才能使得原序列从小到大有序。
输入:
2 1 3 4
输出:
1
思路:
比如:1 3 6 4 5 2
我们观察最大的数6不用移动,
a.6右边的数全部要移动,就是1+1+1=3次(移动的次序不一定,但是次数一定是3)
b.6左边的数,因为排序后和6挨着的一定是4 5,所以前面的两个数不是4 5这样的排序的话一定是移动1+1=2次
c.所以一共需要移动3+2=5次。
综上算法:
1.我们先需要找到最大数所在的序号
2.最大数右边数的个数为a
3.最大数左边的数需要按照自然数的顺序排到N------(N-3, N-2, N-1, N)-----违反规则的个数为b,例如(1 2 5 6 4 3),左边1和2不满足规则的,所以b为2
3.最后的排序的个数为a+b
------下面的代码是借助了一个排完序的数组brr:1 2 3 4 5 6
用i和j从右向左来遍历对比数组,思路是一样的,大家可以画图试一下,只不过麻烦了
直接用上面的思路暴力查找会简单些
import java.util.Arrays;
import java.util.Scanner;
/**
* @author liu
* @Description
*/
public class Main1 {
public static void main(String[] args) {
//输入N
Scanner ss1 = new Scanner(System.in);
int N = ss1.nextInt();
//连续输入n个数,并存入数组中
Scanner ss2 = new Scanner(System.in);
String[] str = ss2.nextLine().split(" ");
int[] a = new int[str.length];
for(int i = 0;i<str.length;i++){
a[i] = Integer.parseInt(String.valueOf(str[i]));
}
//计算次数
int pp = fun(N,a);
System.out.println(pp);
}
//函数
private static int fun(int n, int[] arr) {
//1.得到一个有序的数组brr
int[] brr = arr.clone();
Arrays.sort(brr);
int j = n-1; //记录brr的位置
int sum = 0; //记录移动次数
for(int i = n-1;i>=0; i--){
if(arr[i] == brr[j]){
j--;//相等时brr的j向前移动,for循环中i向前移动了,不用管
}else{
sum++;//不等时,次数加1,for循环中i向前移动了,不用管
}
}
return sum;
}
}
3.杀怪游戏
在X轴上得x点位置,技能可以造成[x-y,x+y]范围内得怪物造成-1点得AOE伤害。问需要多少技能,可以杀死所有怪物
输入:
第一行:n y 怪物得数量和伤害得范围
接下来有n行
-每行:x hp 怪物的位置和怪物的血量
输出:
使用技能的次数
这一题参考牛客网大佬解答:
https://www.nowcoder.com/discuss/457660?type=post&order=time&pos=&page=1&channel=0&source_id=search_post
#include<bits/stdc++.h>
using namespace std;
struct node { //定义怪物结点
int x;
int hp;
}a[100005];
bool cmp(node a, node b) { //结点排序,自定义排序方式
return a.x < b.x;
}
int main()
{
int n,y;
cin >> n >> y;
for(int i = 0; i < n; i++) {
cin >> a[i].x >> a[i].hp;
}
sort(a,a+n,cmp); //对怪物进行排序,防止怪物位置乱序情况
int res = 0, left = 0;
while(left < n) {
int kill = a[left].hp;
res += kill;
int j = left+1;
while(a[j].x <= 2*y + a[left].x) { //在区间的怪物,都相应的减少首个怪物扣除的血量kill
a[j].hp -= kill;
j++;
}
int k = left+1; //往后遍历,找到还有血量的怪物
while(a[k].hp <= 0) {
k++;
}
left = k;
}
cout << res << endl;
return 0;
}