#第一周1005结题报告#
来源:互联网 发布:广告单页设计软件 编辑:程序博客网 时间:2024/05/23 01:12
第一周1005结题报告
Problem Description
Bob enjoys playing computer games, especially strategic games, but sometimes he cannot find the solution fast enough and then he is very sad. Now he has the following problem. He must defend a medieval city, the roads of which form a tree. He has to put the minimum number of soldiers on the nodes so that they can observe all the edges. Can you help him?
Your program should find the minimum number of soldiers that Bob has to put for a given tree.
The input file contains several data sets in text format. Each data set represents a tree with the following description:
the number of nodes
the description of each node in the following format
node_identifier:(number_of_roads) node_identifier1 node_identifier2 … node_identifier
or
node_identifier:(0)
The node identifiers are integer numbers between 0 and n-1, for n nodes (0 < n <= 1500). Every edge appears only once in the input data.
For example for the tree:
the solution is one soldier ( at the node 1).
The output should be printed on the standard output. For each given input data set, print one integer number in a single line that gives the result (the minimum number of soldiers). An example is given in the following table:
Sample Input
4
0:(1) 1
1:(2) 2 3
2:(0)
3:(0)
5
3:(3) 1 4 2
1:(1) 0
2:(0)
0:(0)
4:(0)
Sample Output
1
2
题目意思是以最少的士兵覆盖图中所有道路,刚开始想到用贪心算法,搞了一个n*n的数组,循环处理节点信息,超时,优化了一下贪心算法,复杂度到O(n*n)依然超时,疯了,拿原题百度了一下,树形DP,然而我以前并不知道这是什么,后来仔细研究了一下dp与树形dp,写了,一直wa,检查了两天,一直改,后来上厕所的时候忽然想起来状态转移方程写错了。
每个点要么有士兵,要么没士兵,两种状态,用dp【n】【1】和dp【n】【0】分别表示n点有士兵和n点没士兵的最优解,即最少士兵的个数,包括他本身,因此开始时初始化dp【n】【1】为1,若此点有士兵,则
dp[node][1] +=Math.min(dp[i][0],dp[i][1]);表示儿子节可以有,可以没有,取其最优
若此点没有士兵,子节点必须有
dp[node][0] +=dp[i][1];
然后用递归求出每个点的两种状态,最后取根节点的最优即为结果。
java代码如下:
package 第一周;import java.util.Scanner;public class Main1005_2 { public static int[] father;//父节点 public static int[] visit;//访问标记 public static int[][] dp;//存储状态 public static int child[];//子节点最终没用 public static void treeDp(int node) { visit[node] = 1;// if(child[node]==0){// dp[node][0]= 0;// dp[node][1] = 1;// // }// if(child[node]==1){// dp[node][0]=1;// dp[node][1]=1;// // } for(int i=0;i<visit.length;i++){//递归dp算法 if(visit[i]!=1&&father[i]==node){ treeDp(i); dp[node][1] +=Math.min(dp[i][0],dp[i][1]); dp[node][0] +=dp[i][1]; } } } public static void main(String args[]) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { int n = Integer.parseInt(sc.nextLine()); dp = new int[n][2];// dp[n][1]表示n点选择时的动态规划最优情况 // dp[n][0]表示n点不选时动态规划最优情况 father = new int[n]; visit = new int[n]; child = new int[n]; int root = 0; for(int x =0;x<n;x++){ father[x] = -1; } for (int i = 0; i < n; i++) { dp[i][1] = 1; String s1 = sc.nextLine(); String s11[] = s1.split("\\:|\\)|\\(|\\s+");//拆分输入的字符串,总是出现没有自己想要的拆分结果,正则表达式搞清楚 for (int j = 0; j < Integer.parseInt(s11[2]); j++) {//初始化父节点 father[Integer.parseInt(s11[j + 4])] = Integer .parseInt(s11[0]); } child[Integer.parseInt(s11[0])] = Integer.parseInt(s11[2]); } while(father[root]>-1){//找到根节点 root = father[root]; } treeDp(root); System.out.println(Math.min(dp[root][0],dp[root][1])); } }}
- #第一周1005结题报告#
- 第一周实验报告
- 第一周实验报告1
- 集训第一周解题报告
- #第一周1004解题报告#
- #第一周1001解题报告#
- #第一周1002解题报告#
- #第一周1003解题报告#
- JAVA第一周,信号报告
- ACM解题报告第一周
- 第一周实验报告3-1
- 自主学习报告第一周F_part
- 自主学习报告第一周S_part
- 算法第一周LeetCode解题报告
- 第一周编程题
- 第一周课后题
- 第一周C++上机报告(成绩输出)
- 第一周进度报告 arduino基础编程学习
- UVA_11552_FewestFlops
- Intellij idea 设置
- RocketMQ 源码分析
- 【Android UI】ListView系列二(自定义Adapter订阅新闻栏目)
- js map, reduce, forEach, filter的一般实现
- #第一周1005结题报告#
- 来自豆瓣的一个走过弯路的人(转)
- Swift 懒加载(lazy)
- HttpClient之Post通信与服务器连接实现登陆功能
- 第74讲:从Spark源码的角度思考Scala中的模式匹配学习笔记
- 正则表达式模板大全
- 程序设计策略(设计一款APP的步骤)
- python爬虫(三)--Python的set()
- thinkpad s3 安装win8 kali双系统笔记