52-2018 蓝桥杯省赛 B 组模拟赛(一)java

最近蒜头君喜欢上了U型数字,所谓U型数字,就是这个数字的每一位先严格单调递减,后严格单调递增。比如 212212 就是一个U型数字,但是 333333, 9898, 567567, 3131331313,就是不是U型数字。

现在蒜头君问你,[1,100000][1,100000] 有多少U型数字?

提示:请不要输出多余的符号。

import java.util.Scanner;

public class Main1{
	public static String mp[] = new String[11];
	public static int[][] visit = new int[11][11];
	public static int n, m, ans;
	public static int dx[] = {0, 0, 1, -1};
	public static int dy[] = {1, -1, 0, 0};
	
	public static void main(String[] args) {
		Scanner cin = new Scanner(System.in);
		
		ans = 0;
		//[1,100000] 有多少U型数字?
		for(int i = 100; i <= 100000 ; i++) {
			int a[] = new int[10];
			int t = i;
			int ct = 0;
			while(t!=0) {
				a[ct++] = t % 10;
				t /= 10;
			}
			int jiang = 0;
			int zeng = 0;
			int f = 0;
			int f1 = 0;
			int f2 = 0;
			for(int j = 1; j < ct; j++) {
				if(a[j] < a[j - 1] && f1 == 0) {
					jiang = 1;
					f2 = 1;
				}
				else if(a[j] > a[j - 1] && f2 == 1) {
					zeng = 1;
					f1 = 1;
				}
				else {
					f = -1;
					break;
				}
			}
			if(f != -1 && f1 == 1 && f2 == 1) {
				ans++;
			}
		}
		
		System.out.println(ans);
	}
}

  

 

2.相信大家都知道什么是全排列,但是今天的全排列比你想象中的难一点。我们要找的是全排列中,排列结果互不相同的个数。比如:aab 的全排列就只有三种,那就是aab,baa,aba

代码框中的代码是一种实现,请分析并填写缺失的代码。

import java.util.*;
import java.math.*;

public class Main {
    public static final int N = 1000;
    public static char[] str = new char[N];
    public static char[] buf = new char[N];
    public static int[] vis = new int[N];
    public static int total = 0;
    public static int len = 0;

    public static void arrange(int num) {
        if (num == len) {
            for (int i = 0; i < len; ++i) {
                System.out.print(buf[i]);
            }
            System.out.println();
            total++;
            return;
        }
        for (int i = 0; i < len; ++i) {
            if (vis[i] == 0) {
                int j = 0;
                for (j = i + 1; j < len; ++j) {
                    if (/*在这里填写必要的代码*/) {
                        break;
                    }
                }
                if (j == len) {
                    vis[i] = 1;
                    buf[num] = str[i];
                    arrange(num + 1);
                    vis[i]= 0;
                }
            }
        }
    }

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        str = cin.next().toCharArray();
        total = 0;
        len = str.length;
        buf[len] = '\0';
        int i = 0, j = 0;
        for (i = 0; i < len; ++i) {
            for (j = i + 1; j < len; ++j) {
                if (str[i] > str[j]) {
            		char tmp = str[i];
            		str[i] = str[j];
            		str[j] = tmp;
        		}
            }
        }
        arrange(0);
        System.out.println("Total " + total);
    }
}

  

思路: 就是已经遍历过的就不要重复遍历,可以手动模拟下试试,aaab:   假如 aaab已经用过了, 这次第一个入buf的是第二个a, 然后他从头开始遍历时,发现以前已经用过a了,就不要在用了。

if (str[i] == str[j] && vis[j] == 1) {
                    	//https://nanti.jisuanke.com/t/A1601
                        break;
                    }

  

 

3.对于一个含有 n+2n+2 个元素的数列,A_0, A_1, \cdots A_nA0,A1,An,满足这样的递归公式

 

\displaystyle A_i = \frac{A_{i-1} + A_{i + 1}}{2} - C_i\ \ \ 1 \le i \le nAi=2Ai1+Ai+1Ci   1in

 

现在我们知道 A_0, A_{n + 1}A0,An+1 和 C_1, C_2, \cdots C_nC1,C2,Cn

现在请你帮忙计算 A_1A1 的值。

输入格式

第一行输入一个整数 n(1 \le n \le 1000)n(1n1000)。

第二行输入两个数 A_0A0 和 A_{n+1}An+1,接着是 nn 个数据分别是 C_1,C_2, \cdots C_nC1,C2,Cn。所有的数据均是两位小数的浮点数。

输出格式

输出 A_1A1 的值,结果保留两位小数。

样例输入1复制
1
50.50 25.50
10.15
样例输出1复制
27.85
样例输入2复制
2
-756.89 52.52
172.22 67.17
样例输出2复制
-761.49

java超时:
 for(int i = 2; i <= n + 1; i++) {
        	t.x = 2 * a1.x - a0.x;
        	t.z = 2 * a1.z - a0.z + 2 * c[i - 1];
        	a0 = a1;
        	a1 = t;
//        	System.out.println(t.x + " " + t.z);
        }

  

上面的 a0, a1,t 都是对象,这个赋值会很耗时间,使效率很低。

 
 
        xx a0 = new xx(0, a[0]);
        xx a1 = new xx(1, 0);
        xx t = new xx(0, 0);
        for(int i = 2; i <= n + 1; i++) {
        	t.x = 2 * a1.x - a0.x;
        	t.z = 2 * a1.z - a0.z + 2 * c[i - 1];
        	a0.x = a1.x;
            a0.z = a1.z;
        	a1.x = t.x;
            a1.z = t.z;
//        	System.out.println(t.x + " " + t.z);
        }
        System.out.printf("%.2f\n",(a[n+1] - a1.z) / a1.x);

  

完整答案:

import java.util.*;
import java.math.*;

public class Main {

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        double a[] = new double[1003];
        double c[] = new double[1003];
        
        int n = cin.nextInt();
//        a[0] = cin.nextDouble();
        a[0] = cin.nextDouble();
        a[n+1] = cin.nextDouble();
        
        for(int i = 1; i <= n; i++) {
        	c[i] = cin.nextDouble();
        }
        
        double d = 0;
        double dx = 1;
        xx a0 = new xx(0, a[0]);
        xx a1 = new xx(1, 0);
        xx t = new xx(0, 0);
        for(int i = 2; i <= n + 1; i++) {
        	t.x = 2 * a1.x - a0.x;
        	t.z = 2 * a1.z - a0.z + 2 * c[i - 1];
        	a0.x = a1.x;
            a0.z = a1.z;
        	a1.x = t.x;
            a1.z = t.z;
//        	System.out.println(t.x + " " + t.z);
        }
        System.out.printf("%.2f\n",(a[n+1] - a1.z) / a1.x);
        
    }
}
class xx{
	double x;
	double z;
	xx(){
		
	}
	xx(double x, double z){
		this.x = x;
		this.z = z;
	}
}
/*
 2
1 12
1 2
 */

  

4.蒜头君被暗黑军团包围在一座岛上,所有通往近卫军团的路都有暗黑军团把手。幸运的是,小岛上有一扇上古之神打造的封印之门,可以通往近卫军团,传闻至今没有人能解除封印。

封印之门上有一串文字,只包含小写字母,有 kk 种操作规则,每个规则可以把一个字符变换成另外一个字符。经过任意多次操作以后,最后如果能把封印之门上的文字变换成解开封印之门的文字,封印之门将会开启。

蒜头君战斗力超强,但是不擅计算,请你帮忙蒜头君计算至少需要操作多少次才能解开封印之门。

输入格式

输入第一行一个字符串,长度不大于 10001000,只包含小写字母,表示封印之门上的文字。

输入第二行一个字符串,只包含小写字母,保证长度和第一个字符串相等,表示能解开封印之门的文字。

输入第三行一个整数 k(0 \le k \le 676)k(0k676)。

接下来 kk 行,每行输出两个空格隔开的字符 aa, bb,表示一次操作能把字符 aa 变换成字符 bb。

输出格式

如果蒜头君能开启封印之门,输出最少的操作次数。否则输出一行 -11。

样例输入复制
abcd
dddd
3
a b
b c
c d
样例输出复制
6

思路: 转为最短路径问题.

java交题经验:

1. 读一行提取两个数字,比读两次要快。
//        	char a = cin.next().charAt(0);
//        	char b = cin.next().charAt(0);
        	String t = cin.nextLine();
//        	System.out.println(t + "--");
        	char a = t.charAt(0);
        	char b = t.charAt(2);

 2. String.charAt() 比 将string 转为 char 数组取数要慢, 差别在这题中影响很小。

String s1 = cin.next();
        String s2 = cin.next();
        st = s1.toCharArray();  // 转为数组要快
        end = s2.toCharArray();

  




import java.util.*;
import java.math.*;

public class Main {
	public static int[][] mp = new int[55][55];
	
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        String s1 = cin.next();
        String s2 = cin.next();
        
        int kk = cin.nextInt();
//        System.out.println(s1 + "; " + s2 + "; " + kk);
        for(int i = 0; i < 26; i++) {
    		for(int j = 0; j < 26; j++) {
    			mp[i][j] = 999;
    			mp[i][i] = 0;
    		}
    	}
        cin.nextLine();
        for(int i = 0; i < kk; i++) {
//        	char a = cin.next().charAt(0);
//        	char b = cin.next().charAt(0);
        	String t = cin.nextLine();
//        	System.out.println(t + "--");
        	char a = t.charAt(0);
        	char b = t.charAt(2);
        	if(a != b)
 		       	mp[a - 'a'][b - 'a'] = 1;
        }
        
        for(int k = 0; k < 26; k++) {
        	for(int i = 0; i < 26; i++) {
        		for(int j = 0; j < 26; j++) {
        			if(mp[i][j] > mp[i][k] + mp[k][j]) {
        				mp[i][j] = mp[i][k] + mp[k][j];
        			}
        		}
        	}
        }
        int ans = 0;
        int len = s1.length();
        for(int i = 0; i < len; i++) {
            int x = mp[s1.charAt(i) - 'a'][s2.charAt(i) - 'a'];
        	if(x < 999){
                ans += x;
            }
            else{
                ans = -1;
                break;
            }
        }
        System.out.println(ans);
    }
}
 
/*
abcd
dddd
3
a b
b c
c d
 */

  

import java.util.*;
import java.math.*;

public class Main {
	public static int[][] mp = new int[55][55];
	public static char[] st = new char[1005];
	public static char[] end = new char[1005];
	
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        String s1 = cin.next();
        String s2 = cin.next();
        st = s1.toCharArray();  // 转为数组要快
        end = s2.toCharArray();
        
        int kk = cin.nextInt();
 
        for(int i = 0; i < 26; i++) {
    		for(int j = 0; j < 26; j++) {
    			mp[i][j] = 999;
    			mp[i][i] = 0;  // 自己到自己是0
    		}
    	}
 
        for(int i = 0; i < kk; i++) {
        	char a = cin.next().charAt(0);
        	char b = cin.next().charAt(0);
        	if(a != b)  // 注意
        		mp[a - 'a'][b - 'a'] = 1;
        }
        
        for(int k = 0; k < 26; k++) {
        	for(int i = 0; i < 26; i++) {
        		for(int j = 0; j < 26; j++) {
        			if(mp[i][j] > mp[i][k] + mp[k][j]) {
        				mp[i][j] = mp[i][k] + mp[k][j];
        			}
        		}
        	}
        }
        int ans = 0;
        int len = s1.length();
        for(int i = 0; i < len; i++) {
        	int x = mp[st[i] - 'a'][end[i] - 'a'];
        	if(x < 999){
                ans += x;
            }
            else{
                ans = -1;
                break;
            }
        }
        System.out.println(ans);
    }
}
 
/*
abcd
dddd
3
a b
b c
c d
 */

  

import java.util.*;
import java.math.*;

public class Main {
	public static int[][] mp = new int[55][55];
	
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        String s1 = cin.next();
        String s2 = cin.next();
        
        int kk = cin.nextInt();
//        System.out.println(s1 + "; " + s2 + "; " + kk);
        for(int i = 0; i < 26; i++) {
    		for(int j = 0; j < 26; j++) {
    			mp[i][j] = 999;
    			mp[i][i] = 0;
    		}
    	}
        cin.nextLine();
        for(int i = 0; i < kk; i++) {
//        	char a = cin.next().charAt(0);
//        	char b = cin.next().charAt(0);
        	String t = cin.nextLine();
//        	System.out.println(t + "--");
        	char a = t.charAt(0);
        	char b = t.charAt(2);
        	if(a != b)
 		       	mp[a - 'a'][b - 'a'] = 1;
        }
        
        for(int k = 0; k < 26; k++) {
        	for(int i = 0; i < 26; i++) {
        		for(int j = 0; j < 26; j++) {
        			if(mp[i][j] > mp[i][k] + mp[k][j]) {
        				mp[i][j] = mp[i][k] + mp[k][j];
        			}
        		}
        	}
        }
        int ans = 0;
        int len = s1.length();
        for(int i = 0; i < len; i++) {
            int x = mp[s1.charAt(i) - 'a'][s2.charAt(i) - 'a'];
        	if(x < 999){
                ans += x;
            }
            else{
                ans = -1;
                break;
            }
        }
        System.out.println(ans);
    }
}
 
/*
abcd
dddd
3
a b
b c
c d
 */

  

 

 
      

5.在一个星光摧残的夜晚,蒜头君一颗一颗的数这天上的星星。

蒜头君给在天上巧妙的画了一个直角坐标系,让所有的星星都分布在第一象。天上有 nn 颗星星,他能知道每一颗星星的坐标和亮度。

现在,蒜头君问自己 qq 次,每次他问自己每个矩形区域的星星的亮度和是多少(包含边界上的星星)。

输入格式

第一行输入一个整数 n(1 \le n \le 50000)n(1n50000) 表示星星的数量。

接下里 nn 行,每行输入三个整数 x,y,w(0 \le x, y, w\le 2000)x,y,w(0x,y,w2000),表示在坐标 (x,y)(x,y) 有一颗亮度为 ww 的星星。注意一个点可能有多个星星。

接下来一行输入一个整数 q(1 \le q \le 50000)q(1q50000),表示查询的次数。

接下来 qq 行,每行输入四个整数 x_1, y_1, x_2, y_2x1,y1,x2,y2,其中 (x_1, y_1)(x1,y1) 表示查询的矩形的左下角的坐标,(x_2, y_2)(x2,y2) 表示查询的矩形的右上角的坐标,0 \le x_1 \le x_2 \le 20000x1x22000,0 \le y_1 \le y_2 \le 20000y1y22000。

输出格式

对于每一次查询,输出一行一个整数,表示查询的矩形区域内的星星的亮度总和。

样例输入复制
5
5 0 6
7 9 7
8 6 13
9 7 1
3 0 19
4
0 8 7 9
0 0 7 10
2 7 10 9
5 4 7 5
样例输出复制
7
32
8
0
题目来源

2018 蓝桥杯省赛 A 组模拟赛(一)


思路:本题思路很简单,就是一个dp, 但是有许多注意点,对于c++而言搞一个额外数组标记就可以过,对于java而言,要优化许多才能过,因为java运行慢,输入输出也贼慢。
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;

public class Main {
	public static int[][] mp = new int[2002][2002];
	public static int[][] dp = new int[2002][2002];
	//优化1:加一个数据标记是否已经访问过,因为有大量的0,所以不能借用dp来判断(本题关键优化点)
	public static int[][] visit = new int[2002][2002];
	
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        int n = cin.nextInt();
        int x, y, w;
//        int max_x = 0, max_y = 0;
        for(int i = 0; i < n; i++) {
        	x = cin.nextInt();
        	y = cin.nextInt();
        	w = cin.nextInt();
        	mp[x][y] += w;
//        	max_x = Math.max(x, max_x);    //删了:已通过 6 组测试数据,共 10 组
//        	max_y = Math.max(y, max_y);
        }
        // 优化3: 一次访问到允许范围的最大比较好,应为访问的范围必须覆盖后面询问的最大范围,不能用有星星的最大
        dfs(2000, 2000);
        
        int t = 0;
        int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
        t = cin.nextInt();
//        cin.nextLine();
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < t; i++) {
        	x1 = cin.nextInt();
        	y1 = cin.nextInt();
        	x2 = cin.nextInt();
        	y2 = cin.nextInt();
        	
//        	// 优化2:(本题中优化效果不好,因为后面要提取数组,反而麻烦,要是单个字符就比较好) 只读一次,即一次只读一行, 但是注意,在nextInt()面用nextLine()必须在两者直接在用一个nextLine()
//        	String xx = cin.nextLine();
        	System.out.println(xx);
//        	String[] data = xx.split(" ");
        	for(String xy : data) {
        		System.out.println(xy + "-");
        	}
        	System.out.println(xx.split(" ")[3]);
//        	x1 = Integer.valueOf(data[0]);
//        	y1 = Integer.valueOf(data[1]);
//        	x2 = Integer.valueOf(data[2]);
//        	y2 = Integer.valueOf(data[3]);
        	
        	int allw = 0;
        	allw += dp[x2][y2];
        	if(x1 - 1 >= 0) {
        		allw -= dp[x1-1][y2];
        	}
        	if(y1 - 1 >= 0) {
        		allw -= dp[x2][y1-1];
        	}
        	if(x1 - 1 >= 0 && y1 - 1 >= 0) {
        		allw += dp[x1-1][y1-1];
        	}
        	// 优化4:本题有大量输出,如果每次输出时耗时较大,可以拼接为一个字符串一起输出(本题关键优化点)
//        	System.out.println(allw);
        	sb.append(String.valueOf(allw) + "\n");  
        }
        System.out.println(sb);
//        for(int i = 0; i <= max_x; i++) {
//        	for(int j = 0; j <= max_y; j++) {
//        		System.out.printf("%5d", dp[i][j]);
//        	}
//        	System.out.println();
//        }
    }
    
    public static int dfs(int x, int y) {
    	if(visit[x][y] != 0) {
    		visit[x][y] = 1;
    		return dp[x][y];
    	}
    	if(x == 0 && y == 0) {
    		dp[x][y] = mp[x][y];
    		visit[x][y] = 1;
    		return dp[x][y];
    	}
    	if(x == 0) {
    		visit[x][y] = 1;
    		return dp[x][y] = mp[x][y] + dfs(x, y - 1);
    	}
    	if(y == 0) {
    		visit[x][y] = 1;
    		return dp[x][y] = mp[x][y] + dfs(x - 1, y);
    	}
    	visit[x][y] = 1;
    	return dp[x][y] = mp[x][y] + dfs(x, y - 1) + dfs(x - 1, y) - dfs(x - 1, y -1);
    }
    
}
 
/*
5
5 0 6
7 9 7
8 6 13
9 7 1
3 0 19
4
0 8 7 9
0 0 7 10
2 7 10 9
5 4 7 5

5
1 1 1
2 2 2
3 3 3
4 4 4
2 4 1
3
0 0 1 1
0 0 2 4
1 1 4 4


5
5 0 6
7 9 7
8 6 13
9 7 1
3 0 19
1
0 0 7 10
 */

  

 

转载于:https://www.cnblogs.com/zhumengdexiaobai/p/10575826.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值