package ZhenTi;
import java.sql.SQLOutput;
import java.util.Scanner;
/**
* 5/6喷墨水
*/
public class Solution29 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
sc.nextLine();
String[] strs = sc.nextLine().split(" ");
int[] arr = new int[n];
for(int i=0,c=0; i<strs.length && c<n; i++){
//十六进制变十进制变二进制,前两位0x为前缀
char[] bs = Integer.toBinaryString(Integer.parseUnsignedInt(strs[i].substring(2),16))
.toCharArray();
//长度不足16,后边的用0填充
for(int j=0;j<16-bs.length&&c<n;j++){
arr[c++] = 0;
}
for(int j=0;j<bs.length&&c<n;j++){
arr[c++] = bs[j]- '0';
}
}
// System.out.println(arr);
int ans,ans1=-1,ans2=-1;
//检查向右移动,从0开始遍历,只求最短的,找到了就返回
for(int i=0;i<n;i++){
if(check(arr,i,0)){
ans1 = i;
break;
}
}
//检查向左移动
for(int i=0;i<n;i++){
if(check(arr,i,1)){
ans2 = i;
break;
}
}
ans = (ans1==-1?0:1) + (ans2==-1?0:1);
System.out.println(ans);
if(ans1!=-1){
System.out.println("+" + ans1);
int[] res = new int[n];
for(int i=0;i<n;i++){
if(arr[i]==0){
//输出要求堵塞的孔开启即可,因此先找到堵塞的孔处理
if(arr[i]==0){
res[i-ans1] = 1;
}
}
}
for(int item:res){
System.out.print(item);
}
System.out.println();
}
if(ans2!=-1){
System.out.println("-" + ans2);
int[] res = new int[n];
for(int i=0;i<n;i++){
if(arr[i]==0){
//输出要求堵塞的孔开启即可,因此先找到堵塞的孔处理
if(arr[i]==0){
res[i+ans2] = 1;
}
}
}
for(int item:res){
System.out.print(item);
}
}
}
//cnt表示位移步数,dir表示移动方向,0表示向右移动,1表示向左移动
public static boolean check(int[] arr,int cnt,int dir){
int ans = 0;
int n = arr.length;
if(dir==0){//向右移动
for(int i=0,j;i<n;i++){
//两种情况:不移动可以实现喷墨或者向右移动cnt位也能实现喷墨
if(arr[i]==1 || ((j=i-cnt)>=0&&arr[j]==1 )){
ans++;
}else{
break;
}
}
}else{//向左移动
for(int i=0,j;i<n;i++){
//两种情况:不移动可以实现喷墨或者向左移动cnt位也能实现喷墨
if(arr[i]==1 || ((j=i+cnt)<n&&arr[j]==1 )){
ans++;
}else{
break;
}
}
}
return ans == n;//如果ans等于数组长度n就说明喷墨成功
}
}
复杂的模拟题,塔子哥提交AC
分成数字和特殊字符两部分,转换成数字相加,就不需要考虑进位的问题了
首先,遇到特殊字符就将该位换成0,并记录下特殊字符和位置,最后得到数字部分的值相加。 然后计算特殊字符相加的值,也就是题目中表达式的值乘上10的(所在位置相对小数点的位置)幂次方,比如小数点后一位就乘上10的-1幂次方。 最后转字符串处理并输出。
package ZhenTi;
/**
* 5/6 模拟加法 华为
*/
import java.math.BigDecimal;
import java.util.*;
public class Solution30{
static HashMap<String,Double> sp = new HashMap<>();//特殊字符的加法原则
static StringBuilder spl = new StringBuilder();//记录所有的特殊字符
static BigDecimal cnt = BigDecimal.valueOf(0.0);//记录处理特殊字符后的数字
static int count = 0;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
in.nextLine();
String[] str = in.nextLine().split("\\+");
String left = str[0]; //第一个数
String right = str[1]; //第二个数
HashMap<Integer,Integer> leftSpecial = divide(left);//个数(从0开始):索引
HashMap<Integer,Integer> rightSpecial = divide(right);//得到cnt 用0替代特殊字符后,两个数字之和
//加法规则
sp.put("!+!",0.0);
sp.put("!+@",13.0);sp.put("@+!",13.0);
sp.put("!+#",4.0);sp.put("#+!",4.0);
sp.put("@+@",7.0);
sp.put("@+#",20.0);sp.put("#+@",20.0);
sp.put("#+#",5.0);
//处理特殊字符
int l = spl.length() / 2;//第一个数字的特殊字符的位置和第二数字对应特殊字符位置相差len/2
int index = 0;
for (int i = 0; i < l; i++) {
String temp = spl.charAt(i) + "+" + spl.charAt(l + i);
int idx = left.indexOf('.');//判断是否有小数点
if(idx == -1){//没有小数点, 最终结果为 sum*10^index
index = left.length() - leftSpecial.get(i) - 1;
}else{//有小数点,如果特殊字符在整数部分sum*10^index;小数部分,sum*10^-index
int tem = leftSpecial.get(i);
if(tem < idx){
index = idx - tem - 1;
}else{
index = -(tem - idx);
}
}
Double num = sp.get(temp) * Math.pow(10,index);
String tempnum = String.valueOf(num);
BigDecimal bigtemp = new BigDecimal(tempnum);
cnt = cnt.add(bigtemp);//特殊字符的求和结果
}
//处理结果:去除后置0和小数点
StringBuilder res = new StringBuilder(cnt.toString());
int length = res.length();
while(res.charAt(length -1) == '0'){
res.deleteCharAt(length - 1);
length--;
}
if(res.charAt(length - 1) == '.'){
res.deleteCharAt(length - 1);
}
System.out.println(res);
}
//处理数字:把特殊字符变为0
public static HashMap<Integer,Integer> divide(String str){
int l = str.length();
//存在小数点,返回索引;否则返回-1
int index = str.indexOf(".");
//保存特殊字符索引
HashMap<Integer,Integer> Special = new HashMap<>();//count特殊字符个数-1 : i在字母中对应索引
StringBuilder res = new StringBuilder();
if(index == -1){ //无小数点
for (int i = 0; i < l; i++) { //特殊字符用0替代
if(str.charAt(i) < '0' || str.charAt(i) > '9'){
Special.put(count,i);//放入哈希表
count++;//特殊字符统计个数+1
spl.append(str.charAt(i));//记录特殊字符
res.append('0');//用0代替
}else{//普通字符直接添加
res.append(str.charAt(i));
}
}
}else{ //有小数点,以小数点为间隔做相同的处理 中间加上小数点即可
for (int i = 0; i < index; i++) {
if(str.charAt(i) < '0' || str.charAt(i) > '9'){
//特殊字符;
Special.put(count,i);
count++;
spl.append(str.charAt(i));
res.append('0');
}else{
res.append(str.charAt(i));
}
}
res.append('.');
for (int i = index + 1; i < l; i++) {
//有小数点
if(str.charAt(i) < '0' || str.charAt(i) > '9'){
//特殊字符;
Special.put(count,i);
count++;
spl.append(str.charAt(i));
res.append('0');
}else{
res.append(str.charAt(i));
}
}
}
BigDecimal bigres = new BigDecimal(res.toString());
cnt = cnt.add(bigres);//记录处理特殊字符后的数字,相加,得到数字1和数字2的和
return Special;
}
}
最短路模型
队列元素:x坐标,y坐标,时间轮次
每一个轮次 遍历四个方向 + 停留在原地
package ZhenTi;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Scanner;
/**
* 5/6华为第三题:找公主
*/
public class Solution31 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
//大小,怪物数量
int n = scan.nextInt(), k = scan.nextInt();
boolean[][] traps = new boolean[n][n];//怪物位置
for (int i = 0; i < k; i++) {
traps[scan.nextInt()][scan.nextInt()] = true;
}
//公主和王子的位置
int gx = scan.nextInt(), gy = scan.nextInt(), wx = scan.nextInt(), wy = scan.nextInt();
String[][] strings = new String[n][];
scan.nextLine();
for (int i = 0; i < n; i++) {
strings[i] = scan.nextLine().split(" ");
}
char[][][] grid = new char[n][n][3];//地图表格
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
grid[i][j] = strings[i][j].toCharArray();
}
}
boolean[][][] vis = new boolean[n][n][3];
int[][] dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
Queue<int[]> queue = new ArrayDeque<>();
queue.offer(new int[]{wx, wy, 0});//两个坐标+时间轮次
int ans = 0;
while (!queue.isEmpty()) {
for (int i = queue.size(); i > 0; i--) {
int[] cur = queue.poll();
if (cur[0] == gx && cur[1] == gy) {//找到了公主
System.out.println(ans);
return;
}
int turn = (cur[2] + 1) % 3;//计算当前轮次
for (int[] dir : dirs) {//四个方向搜索
int x = cur[0] + dir[0], y = cur[1] + dir[1];
//边界,是否有怪物,障碍,是否访问过
if (x < 0 || x >= n || y < 0 || y >= n || traps[x][y] || grid[x][y][turn] == '1' || vis[x][y][turn]) continue;
queue.offer(new int[]{x, y, turn});
vis[x][y][turn] = true;
}
//可以选择停留在原地,当下一个轮次没有障碍物且未访问过
if (grid[cur[0]][cur[1]][turn] != '1' && !vis[cur[0]][cur[1]][turn]) {
queue.offer(new int[]{cur[0], cur[1], turn});
vis[cur[0]][cur[1]][turn] = true;
}
}
ans++;//步长
}
System.out.println(-1);
}
}
package ZhenTi;
/**
* 网络最小可达跳数之和
* 多源最短路径BFS
* 参考leetcodeT417. 太平洋大西洋水流问题
*/
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Solution6 {
static int[][] dirs = {{-1,0},{1,0},{0,-1},{0,1}};
static boolean[][] visited;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
String[][] str = new String[n][n];
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
str[i][j] = sc.next();
}
}
visited = new boolean[n][n];
//开始处理:从目标点反向搜索
Queue<int[]> que = new LinkedList<>();
int[][] nums = new int[n][n];//每个点到达终点的步数,BC默认0
int res = 0;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if (str[i][j].equals("C")){
que.offer(new int[]{i,j});
}
}
}
while(!que.isEmpty()){
int[] temp = new int[2];
temp[0] = que.peek()[0];
temp[1] = que.poll()[1];
for(int[] dir:dirs){
int newX = temp[0] + dir[0];
int newY = temp[1] + dir[1];
if(newX<0||newY<0||newX>=n||newY>=n||visited[newX][newY]|| !str[newX][newY].equals("A")){//边界条件+访问过+非A
continue;
}
que.offer(new int[]{newX,newY});
visited[newX][newY] = true;
nums[newX][newY] = nums[temp[0]][temp[1]]+1;
res += nums[newX][newY];
}
}
System.out.println(res);
}
}