1.矿车采矿问题
已知矿场可以划分成N*M的网格图,每个网格存在地形的差异,因此通过不同网格时成本开销存在差异。
网格有以下5种类型:
1.S为运输起点
2.E为运输终点
3.B为阻塞点,不允许通行,
4.C为检查点,矿车在运输路经中,至少需要进入一次检查点。
5.标志为数字的网格,其数字表示经过该网格的成本开销。
运输矿车只能上下左右4个方向运行。注意可重复进入网格。
寻求一条从S网格到E网格,并至少经过一次的检查点的最低成本运输路径,并输出其成本开销。
例如输入:
3 3
S 4 5
7 B 3
C 9 E
输出:16
-----
输入:
3 4
12 B S 13
7 C 4 7
8 3 10 E
输出:15
思路:C为必经点那结果一定是S->C最短+C->E最短 迪杰斯特拉算法
import java.util.*;
public class Main
{
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int n=in.nextInt();
int m=in.nextInt();
in.nextLine();
String[][] matrix =new String[n][m];
for(int i=0;i<n;i++){
matrix[i]=in.nextLine().split(" ");
}
int[][] graph=new int[n][m];
int startX = -1, startY = -1, endX = -1, endY = -1,midX=-1,midY=-1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
String str=matrix[i][j];
if (str.equals("S")) {
startX = i;
startY = j;
graph[i][j]=0;
} else if (str.equals("E")) {
endX = i;
endY = j;
graph[i][j]=0;
}else if(str.equals("C")){
midX = i;
midY = j;
graph[i][j]=0;
}else if(str.equals("B")){
graph[i][j]=Integer.MAX_VALUE;
}else{
graph[i][j]=Integer.parseInt(str);
}
}
}
int left=findMinCostPath(graph,startX,startY,midX,midY);
int right=findMinCostPath(graph,midX,midY,endX,endY);
if(left==0||right==0){
return 0;
}else{
System.out.println(left+right);
}
in.close();
}
public static int findMinCostPath(int[][] graph,int startX,int startY,int endX,int endY) {
int rows = graph.length;
int cols = graph[0].length;
int[][] dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int[] cost = new int[rows*cols];
Arrays.fill(cost,Integer.MAX_VALUE);
cost[startX*cols+startY] = 0;
PriorityQueue<int[]> queue = new PriorityQueue<int[]>(new Comparator<int[]>() {
public int compare(int[] nums1,int[] nums2){
return nums1[2]-nums2[2];
}
});
queue.offer(new int[]{startX, startY,0});
while (!queue.isEmpty()) {
int[] curr = queue.poll();
int x = curr[0];
int y = curr[1];
int d = curr[2];
if(x==endX&&y==endY){
return cost[endX*cols+endY];
}
for (int i=0;i<4;i++) {
int nx = x + dirs[i][0];
int ny = y + dirs[i][1];
if (nx >= 0 && nx < rows && ny >= 0 && ny < cols&&(d+graph[nx][ny]<cost[nx*cols+ny])) {
int newCost = cost[x*cols+y] + graph[nx][ny];
cost[nx*cols+ny] = newCost;
queue.offer(new int[]{nx, ny,newCost});
}
}
}
return 0;
}
}
2.类似零钱兑换
假设有很多不同面额的货币,每个货币只可以使用1次,但可以用不同面额的货币加在一起来购买大面额的商品,但是不想找零,因此对于一些金额的商品,无法进行购买。
比如有 1、2、5 元的货币,我可以购买 了 3元的商品(1+2) ,但是由于5 元无法找零,因此无法购买4元的商品。现给定一个长度为n的正整数数组 money,分别表示n个货币的金额,求出无法购买的商品最小价格。
import java.util.*;
public class Main
{
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int n=in.nextInt();
int[] nums=new int[n];
int sum=0;
for(int i=0;i<n;i++){
nums[i]=in.nextInt();
sum+=nums[i];
}
int[] dp=new int[sum+1];
int max=Integer.MAX_VALUE;
for(int i=0;i<=sum;i++){
dp[i]=max;
}
//01背包问题 先物品再背包
dp[0]=0;
for(int i=0;i<n;i++){
for(int j=sum;j>=nums[i];j--){
if(dp[j-nums[i]]!=max){
dp[j]=Math.min(dp[j],dp[j-nums[i]]+1);
}
}
}
for(int i=0;i<=sum;i++){
if(dp[i]==max){
System.out.println(i);
return;
}
}
System.out.println(sum+1);
}
}
java在线编程 GDBOnline