import java.util.Scanner;
/*
* 题目描述
* 如下图所示,3 x 3 的格子中填写了一些整数。
+--*--+--+
|10* 1|52|
+--****--+
|20|30* 1|
*******--+
| 1| 2| 3|
+--+--+--+
*我们沿着图中的星号线剪开,得到两个部分,每个部分的数字和都是60。
*本题的要求就是请你编程判定:对给定的m x n 的格子中的整数,是否可以分割为两个部分,使得这两个区域的数字和相等。
*如果存在多种解答,请输出包含左上角格子的那个区域包含的格子的最小数目。
*如果无法分割,则输出 0。
*
*输入解释
*程序先读入两个整数 m n 用空格分割 (m,n<10)。
*表示表格的宽度和高度。
*接下来是n行,每行m个正整数,用空格分开。每个整数不大于10000。
*
*输出解释
*输出一个整数,表示在所有解中,包含左上角的分割区可能包含的最小的格子数目。
样例输入1
3 3
10 1 52
20 30 1
1 2 3
样例输出1
3
样例输入2
4 3
1 1 1 1
1 30 80 2
1 1 1 100
样例输出2
10
* 思路
* 深搜-->回溯-->剪枝
*/
public class _09剪格子 {
static int[][] g;//二维数组
static int[][] vis;//标记已访问
private static int n;
private static int m;
private static int total;//总数
private static int ans = Integer.MAX_VALUE;//取最小,可以设置成最大
//i,j表示坐标,steps表示步数,sum表示总和
static void dfs(int i,int j,int steps,int sum) {
if(i < 0 || i == n || j < 0 || j == m || vis[i][j] == 1) {//出口:走出边界或已访问
return;
}
if (sum == total / 2) {//出口:等于总数/2
ans = Math.min(ans, steps);
return;
}
if(sum > total / 2) {//出口:大于总数/2
return;
}
vis[i][j] = 1;//标记已访问
dfs(i-1, j, steps+1, sum+g[i][j]);//往上
dfs(i+1, j, steps+1, sum+g[i][j]);//往下
dfs(i, j-1, steps+1, sum+g[i][j]);//往左
dfs(i, j+1, steps+1, sum+g[i][j]);//往右
vis[i][j] = 0;//重置状态
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
m = sc.nextInt();//行
n = sc.nextInt();//列
g = new int[n][m];//初始化
vis = new int[n][m];//初始化
for(int i = 0;i < n;i++) {
for(int j = 0;j < m;j++) {
g[i][j] = sc.nextInt();//输入数据存入二维数组g
total += g[i][j];//总数
}
}
dfs(0, 0, 0, 0);
System.out.println(ans);
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/*
* 问题描写叙述
* 非常久曾经,T王国空前繁荣。为了更好地管理国家,王国修建了大量的高速路,用于连接首都和王国内的各大城市。
* 为节省经费,T国的大臣们经过思考,制定了一套优秀的修建方案,使得不论什么一个大城市都能从首都直接或者通过其它大城市间接到达。
* 同一时候,假设不反复经过大城市。从首都到达每一个大城市的方案都是唯一的。
* J是T国重要大臣,他巡查于各大城市之间,体察民情。
* 所以,从一个城市马不停蹄地到还有一个城市成了J最常做的事情。他有一个钱袋,用于存放往来城市间的路费。
* 聪明的J发现,假设不在某个城市停下来修整,在连续行进过程中,他所花的路费与他已走过的距离有关,
* 在走第x千米到第x+1千米这一千米中(x是整数),他花费的路费是x+10这么多。
* 也就是说走1千米花费11,走2千米要花费23。
* J大臣想知道:他从某一个城市出发。中间不歇息,到达还有一个城市。全部可能花费的路费中最多是多少呢?
*
* 输入格式
* 输入的第一行包括一个整数n,表示包括首都在内的T王国的城市数
* 城市从1開始依次编号。1号城市为首都。
* 接下来n-1行,描写叙述T国的快速路(T国的快速路一定是n-1条)
* 每行三个整数Pi, Qi, Di。表示城市Pi和城市Qi之间有一条快速路,长度为Di千米。
*
* 输出格式
* 输出一个整数,表示大臣J最多花费的路费是多少。
例子输入1
5
1 2 2
1 3 1
2 4 5
2 5 4
例子输出1
135
* 思路
* 走1千米花费11,走2千米要花费23
* 11+12+13+14+.....==>等差求和 a1*n+n*(n-1)/2
*
* 树的直径:树上任意两节点之间最长的简单路径
* 任意找一个点为根,dfs整棵树找到距离他最远的点xx,再以这个点xx为根求出距离它最远的点yy,(x,y)即为直径
*
*/
public class _10大臣的旅费 {
private static int n;
private static List<Node>[] g;//邻接表
private static int max = -1;
private static int point = -1;
static int disMoney(int dis) {
return 11*dis + dis*(dis-1)/2;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
g = new List[n+1];
for(int i = 1;i <= n;i++) {
g[i] = new ArrayList<Node>();
}
for(int i = 0;i < n-1;i++) {
int a = sc.nextInt();
int b = sc.nextInt();
int c = sc.nextInt();
g[a].add(new Node(b,c));
g[b].add(new Node(a,c));
}
//以1为根,找出距离它最远的点
dfs(1,1,0);//找到point
dfs(point,point,0);
System.out.println(disMoney(max));
}
//from:来自哪个点,num:当前点,dis:累计距离
private static void dfs(int from,int num,int dis) {
boolean isLeaf = true;
List<Node> neighbors = g[num];
for(int i = 0;i < neighbors.size();i++) {
Node neighbor = neighbors.get(i);
if(neighbor.num == from) {
continue;
}
isLeaf = false;
dfs(num,neighbor.num,dis+neighbor.dis);
}
if(isLeaf && dis > max) {//是叶子节点
max = dis;
point = num;
}
}
static class Node{
int num;//编号
int dis;//距离
public Node(int num, int dis) {
this.num = num;
this.dis = dis;
}
}
}