桐希奈娅子 level
获赞
1
粉丝
3
关注
0
看过 TA
25
南昌航空大学
2026
Java
IP属地:江西
暂未填写个人简介
私信
关注
import java.util.ArrayList;import java.util.Scanner;/*** 费用报销 - 二维最大价值 DP(完全背包风格)** 题意:选若干张发票报销,任意两张日期差 ≥ k 天,总金额不超过 m,求最大可报销金额。** 状态定义:dp[i][j] = 只考虑到第 i 天(1..i),在容量恰好为j的情况下,所能存的最大价值* 这道题的状态定义不一样,因为递推关系由i-k转移而来,** 递推:* 1. 不选第 i 天任何票:dp[i][j] = dp[i-1][j]* 2. 选第 i 天的一张票 v:必须从“第 i-k 天及之前”的状态转移(保证与上一张间隔≥k),*    dp[i][j] = max(dp[i][j], dp[i-k][j-v] + v),其中 j >= v* 3. 当 i < k 时,不能从“更早一天”转移,只能把“只选第 i 天一张 v”当作起点:dp[i][v] = max(dp[i][v], v)*/public class Main_Knapsack2D {static Scanner sc = new Scanner(System.in);static int[] pre = {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};public static void main(String[] args) {int n = sc.nextInt();int m = sc.nextInt();int k = sc.nextInt();ArrayList<ArrayList<Integer>> a = new ArrayList<>();for (int i = 0; i <= 365; i++) a.add(new ArrayList<>());for (int i = 0; i < n; i++) {int mon = sc.nextInt();int d = sc.nextInt();int v = sc.nextInt();int day = pre[mon] + d;a.get(day).add(v);}int[][] dp = new int[366][m + 1];// dp[0][*] 已为 0,表示第 0 天、不选任何票时,任意容量下最大金额为 0for (int i = 1; i <= 365; i++) {// 先继承“不选第 i 天”的情况for (int j = 0; j <= m; j++) {dp[i][j] = dp[i - 1][j];}if (i >= k) {// 可以从第 i-k 天转移:选第 i 天的一张票 v,则 j 从 v 到 m,dp[i][j] = max(当前, dp[i-k][j-v]+v)for (int v : a.get(i)) {for (int j = v; j <= m; j++) {dp[i][j] = Math.max(dp[i][j], dp[i - k][j - v] + v);}}} else {// 前 k 天内不能“接”在更早的票后面,只能单独选第 i 天的一张票for (int v : a.get(i)) {if (v <= m) dp[i][v] = Math.max(dp[i][v], v);}}}// 容量维度不一定严格单调,这里安全起见在 0..m 中取最大值作为答案// 这也是为什么说,dp[i][j]是在前i天,容量恰好为j时的最大价值int ans = 0;for (int j = 0; j <= m; j++) {if (dp[365][j] > ans) ans = dp[365][j];}System.out.println(ans);sc.close();}}
0 点赞 评论 收藏
分享
02-19 13:49
已编辑
南昌航空大学 Java
import java.util.*;public class Main {static Scanner sc = new Scanner(System.in);static final int INF = Integer.MAX_VALUE;// 边类:存储邻接表中的边信息static class Edge {public Edge(Integer t, Integer w) {this.t = t;  // 目标节点this.w = w;  // 边权重}Integer t;  // 目标节点编号Integer w;  // 边的权重}public static void main(String[] args) {// 输入:n个节点,m条边int n, m;n = sc.nextInt();m = sc.nextInt();// 邻接表:graph[i]表示从节点i出发的所有边List<List<Edge>> graph = new ArrayList<>();for (int i = 0; i <= n; i++) {graph.add(new ArrayList<>());}// 建图过程int s, t, w;for (int i = 0; i < m; i++) {s = sc.nextInt();  // 起点t = sc.nextInt();  // 终点w = sc.nextInt();  // 权重boolean found = false;// 检查是否已存在s->t的边(处理重边)for (Edge edge : graph.get(s)) {if (edge.t.equals(t)) {  // 找到相同边if (edge.w > w) {    // 保留最小权重edge.w = w;}found = true;break;}}// 如果没有找到相同边,添加新边if (!found) {graph.get(s).add(new Edge(t, w));}}// Dijkstra算法核心数据结构int[] mindist = new int[n + 1];    // 最短距离数组:mindist[i] = 从起点1到i的最短距离boolean[] visited = new boolean[n + 1];  // 访问标记数组:visited[i] = 节点i是否已确定最短路径int start = 1, end = n;  // 起点为1,终点为n// 初始化:起点距离为0,其他为无穷大Arrays.fill(mindist, INF);mindist[start] = 0;// Dijkstra主循环:执行n次(最多n个节点)for (int i = 1; i <= n; i++) {int cur = -1;      // 当前选择的节点int minVal = INF;  // 当前最小距离// 在未访问节点中找距离最小的节点for (int j = 1; j <= n; j++) {if (!visited[j] && mindist[j] < minVal) {minVal = mindist[j];cur = j;}}// 如果没有可选节点,提前退出if (cur == -1) break;visited[cur] = true;  // 标记当前节点已确定最短路径// 松弛操作:更新当前节点的所有邻接点距离for (Edge edge : graph.get(cur)) {// 如果通过cur到edge.t的距离更短,则更新if (mindist[cur] + edge.w < mindist[edge.t]) {mindist[edge.t] = mindist[cur] + edge.w;}}}// 输出结果if (mindist[end] == INF) {  // 无法到达终点System.out.println(-1);} else {  // 可达,输出最短距离System.out.println(mindist[end]);}sc.close();}}
0 点赞 评论 收藏
分享
import java.util.*;public class Main {static Scanner in=new Scanner(System.in);public static void main(String[] args) {int n,m,start;n=in.nextInt();m=in.nextInt();start=in.nextInt();int [][]graph=new int[n+1][n+1];for (int i = 0; i <= n; i++) {Arrays.fill(graph[i],Integer.MAX_VALUE);}for (int i = 0; i < m; i++) {int u = in.nextInt();int v = in.nextInt();int w = in.nextInt();//如果有重边,需要取最小,如果没有直接读入即可graph[u][v] = Math.min(graph[u][v], w);}int[] minDist=new int[n+1];//初始节点为0,其他设为遥不可及Arrays.fill(minDist,Integer.MAX_VALUE);minDist[start]=0;boolean[] visited=new boolean[n+1];//遍历所有节点for (int i=1;i<=n;i++){int cur=start;int minVal=Integer.MAX_VALUE;//找一个数组中最小的那个值并获取最小值的索引for (int j = 1; j <=n ; j++) {if (!visited[j]&&minDist[j]<minVal){minVal=minDist[j];cur=j;}}//标记当前节点访问过visited[cur]=true;//遍历当前节点能直接到达的所有路径,并更新所有未访问节点到原点的距离for (int j = 1; j <=n; j++) {//三个条件:未访问过,新路径比原路径小,当前位置指向的不是遥不可及的节点(也就是可以直接指向)if (!visited[j]&&graph[cur][j]+minDist[cur]<minDist[j]&&graph[cur][j]!=Integer.MAX_VALUE) {minDist[j]=minDist[cur]+graph[cur][j];}}}System.out.print(minDist[1]);for (int i = 2; i <=n ; i++) {System.out.print(" "+minDist[i]);}}}//使用邻接矩阵可能超内存//迪杰斯特拉算法的权值不能有负数
0 点赞 评论 收藏
分享
import java.util.*;public class Main {static Scanner in=new Scanner(System.in);public static void main(String[] args) {int n,m;n=in.nextInt();m=in.nextInt();int []inDegree=new int[n+1];List<List<Integer>> umap=new ArrayList<>();for (int i = 0; i < n; i++) {umap.add(new ArrayList<>());}for (int i = 0; i < m; i++) {int s,t;s=in.nextInt();t=in.nextInt();//记录s指向的节点有哪些,然后让t入度自增umap.get(s).add(t);inDegree[t]++;}//把入度为0的点都加入队列Deque<Integer> queue=new ArrayDeque<>();for (int i = 0; i < n; i++) {if (inDegree[i]==0){queue.offer(i);}}List<Integer>result=new ArrayList<>();//遍历队列while (!queue.isEmpty()){//加入结果int cur=queue.poll();result.add(cur);//获取当前节点指向的节点,并把指向节点的入度减一,如果入度为0加入队列for (Integer i : umap.get(cur)) {inDegree[i]--;if (inDegree[i]==0){queue.offer(i);}}}//如果有节点没有加入,说明成环无答案if (result.size()!=n){System.out.println(-1);return;}System.out.print(result.get(0));for (int i = 1; i <result.size() ; i++) {System.out.print(" "+result.get(i));}}}
0 点赞 评论 收藏
分享
import java.util.Arrays;import java.util.Scanner;public class Main {static Scanner in=new Scanner(System.in);//并查集static int n;static int[] parent;static void init(){for (int i = 1; i <= n; i++) {parent[i]=i;}}static int find(int a){if (parent[a]==a) {return a;}parent[a]=find(parent[a]);return parent[a];}static void join(int a,int b){a=find(a);b=find(b);if (a==b){return;}parent[a]=b;}static boolean isSame(int a,int b){return find(a)==find(b);}//存边的类static class Edge{int u,v,w;public Edge(int u, int v, int w) {this.u = u;this.v = v;this.w = w;}}public static void main(String[] args) {int m;n=in.nextInt();m=in.nextInt();parent=new int[n+1];init();//存边Edge[] edges=new Edge[m];for (int i = 0; i < m; i++) {int u=in.nextInt();int v=in.nextInt();int w=in.nextInt();edges[i]=new Edge(u,v,w);}//排序,(a,b)->a.w-b.w表示从小到大,若b.w-a.w表示从大到小Arrays.sort(edges, (a,b)->a.w-b.w);//used表示一共访问了几条边,ans是权值总和int used=0;int ans=0;//把所有的边取出,判断两个节点是否在一个集合里,如果是,则跳过,如果不在则加入集合并且让ans加上权,标记访问for (Edge edge : edges) {if (isSame(edge.u,edge.v)){continue;}join(edge.u,edge.v);ans+=edge.w;used++;//当找到n-1条边后,跳出循环,注意不要写成returnif (used==n-1){break;}}//如果访问过的节点不是n-1,说明不成环无法连接if (used!=n-1){System.out.println("不成环");}else {System.out.println(ans);}}}
0 点赞 评论 收藏
分享
import java.util.Arrays;import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner in =new Scanner(System.in);int  n= in.nextInt();int  m=in.nextInt();//初始化图为最大数字int[][] grid=new int[n+1][n+1];for (int i = 0; i <=n ; i++) {Arrays.fill(grid[i],Integer.MAX_VALUE);}for (int i = 0; i < m; i++) {int s=in.nextInt();int t=in.nextInt();int v=in.nextInt();//如果有重边,需要取最小,即输入数据可能为:// 2 4 44// 4 2 206// 后面的206会覆盖掉前面的44导致答案错误,需要取最小grid[s][t]=grid[t][s]=Math.min(v,grid[t][s]);}int []mindist=new int[n+1];Arrays.fill(mindist,Integer.MAX_VALUE);//从节点1开始mindist[1]=0;boolean []isInTree=new boolean[n+1];//找n-1条边for (int i =1; i < n; i++) {int minVal=Integer.MAX_VALUE;int cur=-1;//找到最小的权值,获取最小权值和他的索引for (int j=1;j<=n;j++){if (!isInTree[j]&&mindist[j]<minVal){minVal=mindist[j];cur=j;}}//如果除了第一步之外,选到的最小值仍然是max,说明图不联通if (cur==-1){//后面的判断条件可以不写,是等价的||minVal==Integer.MAX_VALUESystem.out.println("不成环");return;}//加入生成树isInTree[cur]=true;//更新所有非生成树节点到树的距离for (int j = 1; j <= n; j++) {if (!isInTree[j]&&grid[cur][j]<mindist[j]){mindist[j]=grid[cur][j];}}}//获取结果int result=0;for (int i = 2; i <=n ; i++) {result+=mindist[i];}System.out.println(result);in.close();}}
0 点赞 评论 收藏
分享

创作者周榜

更多
关注他的用户也关注了:
牛客网
牛客网在线编程
牛客网题解
牛客企业服务