六一儿童节,老师带了很多好吃的巧克力到幼儿园。每块巧克力j的重量为w[j],对于每个小朋友i,当他分到的巧克力大小达到h[i] (即w[j]>=h[i]),他才会上去表演节目。老师的目标是将巧克力分发给孩子们,使得最多的小孩上台表演。可以保证每个w[i]> 0且不能将多块巧克力分给一个孩子或将一块分给多个孩子。
输入描述:
第一行:n,表示h数组元素个数 第二行:n个h数组元素 第三行:m,表示w数组元素个数 第四行:m个w数组元素
输出描述:
上台表演学生人数
输入例子1:
3 2 2 3 2 3 1
输出例子1:
1
思路:贪心,对糖果排序,用当前的糖果满足需求量最大的学生
package l3;
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] a = new int[n];
for(int i=0; i<n; i++)a[i]=sc.nextInt();
int m = sc.nextInt();
int[] b = new int[m];
for(int i=0; i<m; i++)b[i]=sc.nextInt();
Arrays.sort(a);
Arrays.sort(b);
int ret = 0, p = n-1;
for(int i=m-1; i>=0; i--) {
while(p>=0 && b[i] < a[p]) p--;
if(p == -1) break;
ret ++;
p --;
}
System.out.println(ret);
}
}
假设一个探险家被困在了地底的迷宫之中,要从当前位置开始找到一条通往迷宫出口的路径。迷宫可以用一个二维矩阵组成,有的部分是墙,有的部分是路。迷宫之中有的路上还有门,每扇门都在迷宫的某个地方有与之匹配的钥匙,只有先拿到钥匙才能打开门。请设计一个算法,帮助探险家找到脱困的最短路径。如前所述,迷宫是通过一个二维矩阵表示的,每个元素的值的含义如下 0-墙,1-路,2-探险家的起始位置,3-迷宫的出口,大写字母-门,小写字母-对应大写字母所代表的门的钥匙
输入描述:
迷宫的地图,用二维矩阵表示。第一行是表示矩阵的行数和列数M和N 后面的M行是矩阵的数据,每一行对应与矩阵的一行(中间没有空格)。M和N都不超过100, 门不超过10扇。
输出描述:
路径的长度,是一个整数
输入例子1:
5 5 02111 01a0A 01003 01001 01111
输出例子1:
7
思路:BFS,但是自己写下来100+行,而且TLE
package l4;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Set;
public class CopyOfMain {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(), m = sc.nextInt();
sc.nextLine();
char[][] a = new char[n][m];
int x = -1, y = -1;
for(int i=0; i<n; i++) {
String s = sc.nextLine();
a[i] = s.toCharArray();
if(s.indexOf('2') != -1) {
x = i;
y = s.indexOf('2');
}
}
Set<String> visited = new HashSet<String>();
int step = 0;
Queue<Object[]> q = new LinkedList<Object[]>();
Queue<Object[]> qq= new LinkedList<Object[]>();
q.add(new Object[]{x,y,""});
visited.add(x +" " + y + " " + getKeys(a, x, y, ""));
while(true) {
while(!q.isEmpty()) {
Object[] t = q.remove();
int tx = (Integer) t[0], ty = (Integer) t[1];
String keys = (String) t[2];
if(a[tx][ty] == '3') {
System.out.println(step);
return;
}
if(tx > 0 && canPass(a, tx-1, ty, keys)) {
String tmpKeys = getKeys(a, tx-1, ty, keys);
String tmp = tx-1 + " " + ty + " " + tmpKeys;
if(!visited.contains(tmp)) {
visited.add(tmp);
qq.add(new Object[]{tx-1, ty, tmpKeys}); // 这里应该放keys
}
}
if(ty > 0 && canPass(a, tx, ty-1, keys)) {
String tmpKeys = getKeys(a, tx, ty-1, keys);
String tmp = tx + " " + (ty-1) + " " + tmpKeys;
if(!visited.contains(tmp)) {
visited.add(tmp);
qq.add(new Object[]{tx, ty-1, tmpKeys});
}
}
if(tx < n-1 && canPass(a, tx+1, ty, keys)) {
String tmpKeys = getKeys(a, tx+1, ty, keys);
String tmp = tx+1 + " " + ty + " " + tmpKeys;
if(!visited.contains(tmp)) {
visited.add(tmp);
qq.add(new Object[]{tx+1, ty, tmpKeys});
}
}
if(ty < m-1 && canPass(a, tx, ty+1, keys)) {
String tmpKeys = getKeys(a, tx, ty+1, keys);
String tmp = tx + " " + (ty+1) + " " + tmpKeys;
if(!visited.contains(tmp)) {
visited.add(tmp);
qq.add(new Object[]{tx, ty+1, tmpKeys});
}
}
}
q = qq;
qq = new LinkedList<Object[]>();
step ++;
if(q.isEmpty()) break;
}
System.out.println(-1);
}
private static boolean canPass(char[][] a, int i, int j, String keys) {
return a[i][j]=='1' || a[i][j]=='2' || a[i][j]=='3' || (a[i][j]>='a'&&a[i][j]<='z')
|| (a[i][j]>='A'&&a[i][j]<='Z'&&keys.indexOf(a[i][j])!=-1);
}
private static String getKeys(char[][] a, int i, int j, String keys) {
if(a[i][j]>='a' && a[i][j]<='z')
keys += (""+a[i][j]).toUpperCase();
if(a[i][j]>='A' && a[i][j]<='Z') {
int idx = keys.indexOf(a[i][j]);
if(idx != -1) keys = keys.substring(0, idx) + keys.substring(idx+1);
}
return keys;
}
}
有2个trick
1. 用integer表示10中=种钥匙
2. 因为时间是限制AC的主要因素,用数组比HashSet好
package l4;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
/*
* 写博客的时候看下牛客的讨论区
* 用数组可AC
*
* 此可以作为BFS的模板
*
* 反正key最多10个,用int足矣
* 状态也可以用个数组表示,
*/
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(), m = sc.nextInt();
sc.nextLine();
char[][] a = new char[n][m];
int x = -1, y = -1;
for(int i=0; i<n; i++) {
String s = sc.nextLine();
a[i] = s.toCharArray();
if(s.indexOf('2') != -1) {
x = i;
y = s.indexOf('2');
}
}
boolean[][][] visited = new boolean[n][m][1100];
int step = 0;
Queue<int[]> q = new LinkedList<int[]>();
Queue<int[]> qq= new LinkedList<int[]>();
q.add(new int[]{x,y,0});
visited[x][y][0] = true;
int[][] next = {{-1,0}, {0,-1}, {1,0}, {0,1}};
while(true) {
while(!q.isEmpty()) {
int[] t = q.remove();
for(int i=0; i<4; i++) {
int newx = t[0]+next[i][0], newy = t[1]+next[i][1], keys = t[2];
if(newx<0||newx>=n||newy<0||newy>=m||a[newx][newy]=='0') continue;
if(a[newx][newy]=='3') {
System.out.println(step+1);
return;
} else if(a[newx][newy]>='a' && a[newx][newy]<='z') {
// 钥匙可以重复利用
keys = (keys | (1<<(a[newx][newy]-'a')));
} else if(a[newx][newy]>='A' && a[newx][newy]<='Z') {
if((keys & (1<<(a[newx][newy]-'a'))) == 0)
continue;
}
if(visited[newx][newy][keys]) continue;
visited[newx][newy][keys] = true;
qq.add(new int[]{newx, newy, keys});
}
}
// q,qq可以合并为一个linkedlist,把step信息放到数组里面即可
q = qq;
qq = new LinkedList<int[]>();
step++;
}
}
}