原题链接
题目描述
有一只生命值为H
的怪物,它有N
瓶药水,编号为 1 ∼ N 1 \sim N 1∼N( P i < P j , i < j P_i \lt P_j, i \lt j Pi<Pj,i<j),第 i i i 瓶药水可以给怪物恢复 P i P_i Pi点生命值,问怪物喝哪瓶药水可以让 H + P i H+P_i H+Pi最少可以达到X
,输入那瓶药水的编号。思路:二分
- P值有序,直接二分
public static void solve() throws IOException{
int n = readInt(), H = readInt(), X = readInt();
int[] p = utils.nextIntArray(n);
int l = 0, r = n + 1;
while (l + 1 < r) {
int mid = (l + r) / 2;
if (p[mid] + H >= X) {
r = mid;
} else {
l = mid;
}
}
printWriter.println(r);
}
原题链接
题目描述
有 N + 1 N+1 N+1个连续的数字,现在给出 N N N个数字,输出缺少的那个数字(答案确保这个数字唯一)。思路:排序
public static void solve() throws IOException {
int n= readInt();
int[] arr = utils.nextIntArray(n);
Arrays.sort(arr, 1, n + 1);
int a = arr[1];
for (int i = 2; i <= n; i++) {
if (arr[i] != a + 1) {
printWriter.println(a + 1);
return;
}
a = arr[i];
}
}
原题链接
题目描述
有N
个点,M
条双向边,第i
条边是点 A i A_i Ai到点 B i B_i Bi的距离,求一个点到另一个点到达的最长距离。样例输入
4 4 1 2 1 2 3 10 1 3 100 1 4 1000
样例输出
1110
思路:dfs
- 由于数据范围比较小,考虑枚举从每个点出发所能贡献的最大距离。
static int n, m;
static int[][] g;
static boolean[] st;
static long sum = 0;
public static void solve() throws IOException {
n = readInt(); m = readInt();
g = new int[n + 1][n + 1];
while (m-- > 0) {
int a = readInt(), b = readInt(), c = readInt();
//双向边
g[a][b] = Math.max(g[a][b], c);
g[b][a] = Math.max(g[b][a], c);
}
for (int i = 1; i <= n; i++) {
st = new boolean[n + 1];
st[i] = true;
dfs(i, 0);
}
printWriter.println(sum);
}
public static void dfs(int x, int curSum) {
sum = Math.max(sum, curSum);
for (int i = 1; i <= n; i++) {
//这个点 i没有被访问过而且这两个点 i和 x有连边
if (!st[i] && g[x][i] != 0) {
st[i] = true;
dfs(i, curSum + g[x][i]);
st[i] = false;
}
}
}
原题链接
题目描述
有N
个选区,第i
个选区有 X i + Y i X_i+Y_i Xi+Yi个选民,其中 X i X_i Xi个会给高桥投票, Y i Y_i Yi个会给青木投票,赢得第i
个选区会获得 Z i Z_i Zi个席位,谁获得的席位最多,则赢得选举,问最少需要多个选民从青木转到高桥,高桥才会赢。样例输入
2 3 6 2 1 8 5
样例输出
4
思路:01背包
- 考虑将每一个选区视为一件物品
- 物品的体积为 Z i Z_i Zi, 物品的价值为 X i ≥ Y i ? 0 : ( Y i − X i + 1 ) / 2 X_i \ge Y_i ? \ 0 : (Y_i - X_i + 1) / 2 Xi≥Yi? 0:(Yi−Xi+1)/2
dp
数组的定义为在总票数为j
时所需要的最少的转向投票的人数- 最后再枚举一下总票数超过一半的情况下,需要的最少的转向投票的人数
public static void solve() throws IOException{
int n = readInt();
long inf = utils.forceLong(1e18);//注意不能初始化为Long.MAX_VALUE,可能会溢出
int sum = 0;
int[] a = new int[n + 1], b = new int[n + 1], c = new int[n + 1];
for (int i = 1; i <= n; i++) {
a[i] = readInt(); b[i] = readInt(); c[i] = readInt();
sum += c[i];
}
long[] dp = new long[sum + 1];
Arrays.fill(dp, inf);
dp[0] = 0;
for (int i = 1; i <= n; i++) {
for (int j = sum; j >= c[i]; j--) {
dp[j] = Math.min(dp[j], dp[j - c[i]] + (a[i] >= b[i] ? 0 : (b[i] - a[i] + 1) / 2));
}
}
int cur = (sum + 1) / 2;
long res = Long.MAX_VALUE;// 枚举总票数超过一半的情况下,需要的最少的转向投票的人数
for (int i = cur; i <= sum; i++) {
res = Math.min(res, dp[i]);
}
printWriter.println(res);
}
原题链接
题目描述
有个N
行W
列的字符矩阵,每个字符的含义如下:
.
:可通过#
:不可通过^,>,v,<
:分别表示有个人朝着上右下左四个方向,无法通过。人的视线沿人面对的方向笔直延伸,并被障碍物或其他人阻挡S
:起点,且只有一个,而且不会在他人视线内G
:终点,且只有一个,而且不会在他人视线内样例输入
5 7 ....Sv. .>..... ....... ..<.#< ^G....>
样例输出
15
思路:bfs
- 先预处理出不能走的点,并将其赋值为
!
- 在bfs一遍找到最短路径
public static void solve() throws IOException {
int n = readInt(), m = readInt();
char[][] map = utils.nextCharArray(n, m);
int sx = -1, sy = -1, ex = -1, ey = -1;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
char ch = map[i][j];
if (ch == 'S') {
sx = i; sy = j;
} else if (ch == 'G') {
ex = i; ey = j;
} else if (ch == '^') {
int p = i - 1;
//将该点朝上的点赋值为!
while (p >= 1 && (map[p][j] == '.' || map[p][j] == '!')) {
map[p][j] = '!';
p--;
}
} else if (ch == '>') {
int p = j + 1;
//将该点朝右的点赋值为!
while (p <= m && (map[i][p] == '.' || map[i][p] == '!')) {
map[i][p] = '!';
p++;
}
} else if (ch == '<') {
int p = j - 1;
//将该点朝左的点赋值为!
while (p >= 1 && (map[i][p] == '.' || map[i][p] == '!')) {
map[i][p] = '!';
p--;
}
} else if (ch == 'v') {
int p = i + 1;
//将该点朝下的点赋值为!
while (p <= n && (map[p][j] == '.' || map[p][j] == '!')) {
map[p][j] = '!';
p++;
}
}
}
}
Deque<Pair> deque = new LinkedList<>();
int[][] dist = new int[n + 1][m + 1];
dist[sx][sy] = 0; map[sx][sy] = '!';
deque.offer(new Pair(sx, sy));
while (deque.size() > 0) {
Pair p = deque.poll();
for (int i = 0; i < 4; i++) {
int nx = p.first + dx[i], ny = p.second + dy[i];
if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && (map[nx][ny] == '.' || map[nx][ny] == 'G')) {
dist[nx][ny] = dist[p.first][p.second] + 1;
if (map[nx][ny] == 'G') {
printWriter.println(dist[nx][ny]);
return;
}
map[nx][ny] = '!';
deque.offer(new Pair(nx, ny));
}
}
}
printWriter.println(-1);
}