第一题
题目
在一个3* 3的棋盘上,小红和小紫正在玩“夹吃棋”。所谓“夹吃棋”,即如果存在一个白子,它的两侧 (横向或者纵向)相邻都是黑子,则这个棋子将被“夹吃”,对于黑棋亦然。如果一个棋盘的局面没有一方被夹吃,或者黑白双方都被对面夹吃,则认为是平局。如果只有一方夹吃了另一方,则认为夹吃方赢,被夹吃方输。小红执黑棋,小紫执白棋,现在给定一个局面,请你判断当前棋局是谁获胜。
输入描述
第一行输入一个正整数t,代表询问的次数。
接下来每组询问输入三行,每行是一个长度为3的字符串,字符串仅由’o’,‘.’,'*'组成。
其中o代表白棋,*代表黑棋,.代表未放置棋子。
输出描述
小红获胜输出“kou”,小紫获胜输出“yukan”,平局输出“draw”。
样例输入
3
…
oo
…
o**
ooo
…
oo
o
oO
样例输出
yukari
kou
draw
参考题解
遍历棋盘,如果未放置棋子,则跳过;若有棋子,则判断其是否被上下或者左右的棋子“夹吃”,用两个变量分别记录小红和小紫是否有棋子被夹吃。遍历完成后通过两个变量再判断最终结果。
public class jd01 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
List<String> res= new ArrayList<>();
int t=sc.nextInt();
sc.nextLine();
char [][]g=new char[3][3];
for (int i = 0; i < t; i++) {
for (int j = 0; j < 3; j++) {
String row=sc.nextLine();
for (int k = 0; k < 3; k++) {
g[j][k]=row.charAt(k);
}
}
System.out.println(winwin(g));
}
}
public static String winwin(char [][] g){
boolean kou = false,yukari=false;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if(g[i][j]=='.') continue;
else {
//判断列
if(i-1>=0&&i+1<3){
//和领行不相等,且邻行不是空
if(g[i][j]!=g[i-1][j]&&g[i-1][j]==g[i+1][j]&&g[i-1][j]!='.'){
if(g[i][j]=='o') kou=true;
else yukari=true;
}
}
//判断行
if(j-1>=0&&j+1<3){
//和领行不相等,且邻行不是空
if(g[i][j]!=g[i][j-1]&&g[i][j-1]==g[i][j+1]&&g[i][j-1]!='.'){
if(g[i][j]=='o') kou=true;
else yukari=true;
}
}
}
}
}
if(kou&&yukari) return "draw";
else if(kou) return "kou";
else return "yukari";
}
}
第二题
题目
小红准备买n件物品,第i件物品的价格是ai。另外,小红有m种优惠券,第i个优惠券是mi:买一件价格不小于bi的商品时,可以减去ci的价格。每件商品最多只能用一次优惠券。每种优惠券可以用多次。
小红想知道,自己买全部商品最少需要花多少钱?
输入描述
第一行输入两个正整数代表商品数量和优惠券的种类数。
第二行输入n个正整数ai代表每件商品的价格。
接下来的m行,每行输入两个正整数b,C,代表第种优惠券的信息
1<n,m<200000
1 <ai < 10^9
1<ci<bi<10^9
输出描述
一个正整数,代表最终需要花的最少钱数。
样例输入
输入
3 2
4 8 6
5 1
8 5
输出
12
说明
第二件商品选择第二种优惠券,价格减到了3元;第三件商品选择第一种优惠券,价格减到了5元。总花费:4+3+5=12
参考题解
将优惠卷按照起减额度递增排序,再对满减额度递增排序(也可以直接去重,本文是排序),对每件商品找到最大的优惠(这里使用二分)
public class jd02 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n,m;
n=sc.nextInt();
m=sc.nextInt();
int[] a = new int[n];
int [][] b=new int[m][2];
for (int i = 0; i < n; i++) {
a[i]=sc.nextInt();
}
for (int i = 0; i < m; i++) {
b[i][0]=sc.nextInt();
b[i][1]=sc.nextInt();
}
//满减b1从小到大,满减额度c1从大到小
Arrays.sort(b,((o1, o2) -> {
if(o1[0]==o2[0]) return o2[1]-o1[1];
return o1[0]-o2[0];
}));
double res=0;
for (int i = 0; i < n; i++) {
int index=search(b,a[i]);
if(a[i]>=b[0][0]) res+=a[i]-b[index][1];
else res+=a[i];
}
System.out.println(res);
}
public static int search(int [][] b,int price){
int l=0,r=b.length-1,res=-1;
while (l<=r) {
int m=l+(r-l)/2;
if(b[m][0]<=price) {
res=m;
l=m+1;
}
else {
r=m-1;
}
}
return res;
}
}
第三题
题目
给定一个正整数x,小红每次操作可以选择x的一个二进制位中的1,并加上这个二进制位或者减去这个二进制位对应的十进制的值。小红希望在有限的操作次数内变成y。你能帮帮她吗?
两个正整数x,y,用空格隔开。
输入描述
两个正整数x,y,用空格隔开
1<=x,y <= 10^18
输出描述
如果无解,请直接输出-1.
否则第一行输入一个整数t,代表操作次数。接下来的t行,每行输入一个字符op (‘+‘或者’-’)、空格、一个正整数i代表每次操作.请务必保证操作次数不超过 1000,且操作选择的数必须是当前的x中存在的二进制的“1’(输出时请输出那个1对应的十进制的值)有多解时输出任意即可。
样例输入
输入:
3 8
输出:
2
+1
+4
说明:
以下输出也可以
3
-1
+2
+4
参考题解
根据x和y的相对大小,逐步调整x,用lowbit( num&-num)找到差值二进制1的最后一位,将x调整,操作加入res中(这里等于x==y的情况也是返回的-1,可以根据题目调整)
public class jd03 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
long x = scanner.nextLong();
long y = scanner.nextLong();
List<String> operations = findOperations(x, y);
if (operations.isEmpty()||operations.size()>1000) {
System.out.println("-1");
} else {
System.out.println(operations.size());
for (String op : operations) {
System.out.println(op);
}
}
}
public static List<String> findOperations(long x, long y) {
List<String> operations = new ArrayList<>();
while (x != y) {
if (x < y) {
long diff = y - x;
long lowestSetBit = diff & -diff;
operations.add("+" + lowestSetBit );
x += lowestSetBit;
} else {
long diff = x - y;
long lowestSetBit = diff & -diff;
operations.add("-" + lowestSetBit);
x -= lowestSetBit;
}
}
return operations;
}
}
全是暴力求解,水了…