- 2022-06-20:一个二维矩阵,上面只有 0 和 1,只能上下左右移动,
如果移动前后的元素值相同,则耗费 1 ,否则耗费 2。
问从左上到右下的最小耗费。
来自网易。3.27笔试。
建立模型:
/**
* 求解花费的最小代价
* 建模:dijskra模型来使用
* 步骤:a.初始时,s只包含源点,即s={v},v的距离为0,U包含除v外的其他顶点,即:U={其余顶点},若v与U中顶点有边,则<u,v>正常有权值,若u不是v的出边邻接点,则<u,v>权值为无穷大。
* b.从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)
* c.以k为新考虑的中间点,修改U中个顶点的距离;若从源点v到顶点u的距离(经过k)比原来距离(不经过k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权
* d.重复步骤b和c直到所有顶点都包含在s中。
*
* 这个模型是可以求解最短距离问题,最少开销问题,
*
* @param map
* @return
*/
public static int bestWalk(int[][] map) {
int n = map.length;
int m = map[0].length;
//小根堆:【代价,行,列】
//根据代价,谁代价小,谁放在堆的上面
PriorityQueue<int[]> heap = new PriorityQueue<>((a, b) -> a[0] - b[0]);
//poped[i][j] == true 已经弹出过了!不要再处理,直接忽略
//poped[i][j] == false 之间(i,j)没弹出过!要处理
boolean[][] poped = new boolean[n][m];
heap.add(new int[]{0, 0, 0});
int ans = 0;
while (!heap.isEmpty()) {
//当前弹出,【代价,行,列】,当前位置
//当前弹出的是各个方向中最小代价的
int[] cur = heap.poll();
int dis = cur[0];
int row = cur[1];
int col = cur[2];
if (poped[row][col]) {
continue;
}
//第一次弹出
poped[row][col] = true;
//到达最终的端点
if (row == n - 1 && col == m - 1) {
ans = dis;
break;
}
add(dis, row - 1, col, map[row][col], n, m, map, poped, heap);
add(dis, row + 1, col, map[row][col], n, m, map, poped, heap);
add(dis, row, col - 1, map[row][col], n, m, map, poped, heap);
add(dis, row, col + 1, map[row][col], n, m, map, poped, heap);
}
return ans;
}
/**
* @param preDistance 之前的距离
* @param row 当前要加入的是什么位置
* @param col
* @param preValue 前一个格子是什么值
* @param n 边界
* @param m
* @param map 每一个格子的值,都在map里
* @param poped 当前位置如果是弹出过的位置,要忽略
* @param heap 小根堆
*/
public static void add(int preDistance, int row, int col, int preValue, int n, int m, int[][] map, boolean[][] poped, PriorityQueue<int[]> heap) {
if (row>=0 && row<n && col>=0 && col<m && !poped[row][col]){
heap.add(new int[]{preDistance+(map[row][col] == preValue ?1:2),row,col});
}
}
/**
* 新建模型:求解多个满足条件下面,最好的城市编号
* 模型:Floyd模型
*
* @param n n个城市
* @param edges 城市之间的开销
* @param distanceThreshold 一定的金额
* @return 最好的方案
*/
public int findTheCity(int n, int[][] edges, int distanceThreshold) {
int dist[][] = new int[n][n];//存储距离
//初始化
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
dist[i][j] = 1000000;
}
dist[i][i] = 0;
}
//再赋值
for (int arr[] : edges) {
dist[arr[0]][arr[1]] = arr[2];
dist[arr[1]][arr[0]] = arr[2];
}
//计算
for (int k = 0; k < n; k++) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
dist[i][j] = Math.min(dist[i][j], dist[i][k] + dist[k][j]);
}
}
}
int min = Integer.MAX_VALUE;
int minIndex = 0;
int pathNum[] = new int[n];//存储距离
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (dist[i][j] <= distanceThreshold) {
pathNum[i]++;
}
}
if (pathNum[i] <= min) {
min = pathNum[i];
minIndex = i;
}
}
return minIndex;
}