题目一:完美的代价
问题描述:
回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。(时间限制:1.0s,内存限制:512.0MB)
交换的定义是:交换两个相邻的字符
例如mamad
第一次交换 ad : mamda
第二次交换 md : madma
第三次交换 ma : madam (回文!完美!)
输入、输出格式:
第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
第二行是一个字符串,长度为N.只包含小写字母
如果可能,输出最少的交换次数。
否则输出Impossible
解决思路:
- 我们先画一个简图:
(1)将end处的字符与begin处的字符进行比较,如果相等:将end处的字符移动到字符串末端,计算出移动的次数,begin向后移动一个字符end向前移动一个字符并重复(1)的操作。
(2)如果不相等:将end向前移动一个字符,重复(1)的操作直到遇到begin。
- 我们需要注意,如果没有找到与字符串第一个字符相等的字符,那说明该字符很有可能是中间字符,此时我们直接计算将该字符移到数组中间的次数即可,并且将begin向前移动一个字符重复(1)的操作即可。
解决代码:
import java.util.Scanner;
public class Main {
private static int times = 0;
private static boolean isMiddle = false;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
String s = sc.next();
char[] chs = s.toCharArray();
if(perfect(chs,0, N-1)) {
System.out.println(times);
}
else {
System.out.println("Impossible");
}
}
private static boolean perfect(char[] chs, int begin, int end) {
if(begin >= end) {
return true;
}
for(int i = end; i > begin; i--) {
if(chs[i] == chs[begin]) {
move(chs, i, end);
times += (end - i);
return perfect(chs, begin+1, end-1);
}
}
if(!isMiddle) {
isMiddle = true;
times += (chs.length / 2 - begin);
return perfect(chs, begin+1, end);
}
return false;
}
/**
* 将数组中的指定字符移动到指定位置
* @param chs:字符数组
* @param target:指定字符的位置
* @param des:目标的位置
*/
private static void move(char[] chs, int target, int des) {
char c = chs[target];
for(int i = target; i < des; i++) {
chs[i] = chs[i+1];
}
chs[des] = c;
}
}
题目二:矩形面积交
问题描述:
平面上有两个矩形,它们的边平行于直角坐标系的X轴或Y轴。对于每个矩形,我们给出它的一对相对顶点的坐标,请你编程算出两个矩形的交的面积。(时间限制:1.0s,内存限制:512.0MB)
输入、输出格式:
输入仅包含两行,每行描述一个矩形。
在每行中,给出矩形的一对相对顶点的坐标,每个点的坐标都用两个绝对值不超过10^7的实数表示。
输出仅包含一个实数,为交的面积,保留到小数后两位。
解决思路:
-
由于后面计算相交矩形的面积时需要知道矩形的长和宽,而长和宽是根据横纵坐标算出的,所以我们将横、纵坐标分别存储在两个数组中。
-
判断两个矩形不相交的思路:通过画图,两个矩形不相交的相对位置有4种情况(上、下、左、右),并且所给矩形的对角线也有两种情况(递增和递减)。
-
计算相交矩形长和宽的思路:我们可以先画一个简图:
得出上图中红色字体的公式是有前提的,即:arr1[3] > arr1[1] > arr1[2] > arr1[0]和arr2[3] > arr2[1] > arr2[2] > arr2[0],所以我们在计算之前可以先对横纵坐标数组分别进行排序,再计算即可。
解决代码:
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
double[] arr1 = new double[4]; // 存储横坐标
double[] arr2 = new double[4]; // 存储纵坐标
for (int i = 0; i < 4; i++) {
arr1[i] = sc.nextDouble();
arr2[i] = sc.nextDouble();
}
// 两个矩形不相交有四种相对位置,取最大最小值是由于矩形有两条对角线
if ((Math.max(arr1[0], arr1[1]) <= Math.min(arr1[2], arr1[3])) || (Math.max(arr1[2], arr1[3]) <= Math.min(arr1[0], arr1[1])) ||
(Math.max(arr2[0], arr2[1]) <= Math.min(arr2[2], arr2[3]) || (Math.max(arr2[2], arr2[3]) <= Math.min(arr2[0], arr2[1])))) {
System.out.println("0.00");
}
else {
Arrays.sort(arr1);
Arrays.sort(arr2);
double i = arr1[2] - arr1[1];
double j = arr2[2] - arr2[1];
System.out.println(String.format("%.2f", i*j));
}
}
}