一 原题
The fences that surround Farmer Brown's collection of pastures have gotten out of control. They are made up of straight segments from 1 through 200 feet long that join together only at their endpoints though sometimes more than two fences join together at a given endpoint. The result is a web of fences enclosing his pastures. Farmer Brown wants to start to straighten things out. In particular, he wants to know which of the pastures has the smallest perimeter.
Farmer Brown has numbered his fence segments from 1 to N (N = the total number of segments). He knows the following about each fence segment:
- the length of the segment
- the segments which connect to it at one end
- the segments which connect to it at the other end.
Given a list of fence segments that represents a set of surrounded pastures, write a program to compute the smallest perimeter of any pasture. As an example, consider a pasture arrangement, with fences numbered 1 to 10 that looks like this one (the numbers are fence ID numbers):
1
+---------------+
|\ /|
2| \7 / |
| \ / |
+---+ / |6
| 8 \ /10 |
3| \9 / |
| \ / |
+-------+-------+
4 5
The pasture with the smallest perimeter is the one that is enclosed by fence segments 2, 7, and 8.
PROGRAM NAME: fence6
INPUT FORMAT
| Line 1: | N (1 <= N <= 100) |
| Line 2..3*N+1: | N sets of three line records:
|
SAMPLE INPUT (file fence6.in)
10 1 16 2 2 2 7 10 6 2 3 2 2 1 7 8 3 3 3 2 1 8 2 4 4 8 1 3 3 9 10 5 5 8 3 1 9 10 4 6 6 6 1 2 5 1 10 7 5 2 2 1 2 8 9 8 4 2 2 2 3 7 9 9 5 2 3 7 8 4 5 10 10 10 2 3 1 6 4 9 5
OUTPUT FORMAT
The output file should contain a single line with a single integer that represents the shortest surrounded perimeter.SAMPLE OUTPUT (file fence6.out)
12
二 分析
三 代码
USER: Qi Shen [maxkibb3] TASK: fence6 LANG: C++ Compiling... Compile: OK Executing... Test 1: TEST OK [0.000 secs, 4264 KB] Test 2: TEST OK [0.000 secs, 4264 KB] Test 3: TEST OK [0.000 secs, 4264 KB] Test 4: TEST OK [0.000 secs, 4264 KB] Test 5: TEST OK [0.000 secs, 4264 KB] Test 6: TEST OK [0.000 secs, 4264 KB] Test 7: TEST OK [0.000 secs, 4264 KB] Test 8: TEST OK [0.000 secs, 4264 KB] Test 9: TEST OK [0.000 secs, 4264 KB] All tests OK.
Your program ('fence6') produced all correct answers! This is your submission #4 for this problem. Congratulations!
/*
ID:maxkibb3
LANG:C++
PROB:fence6
*/
#include<cstdio>
const int MAX = 105;
const int INF = 0x7fffffff;
int n;
int len[MAX];
int pre_num[MAX], next_num[MAX];
int pre[MAX][MAX], next[MAX][MAX];
bool vis[MAX];
int ans = INF;
void init() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
int idx;
scanf("%d", &idx);
scanf("%d%d%d", &len[idx], &pre_num[idx], &next_num[idx]);
for(int i = 0; i < pre_num[idx]; i++) scanf("%d", &pre[idx][i]);
for(int i = 0; i < next_num[idx]; i++) scanf("%d", &next[idx][i]);
}
}
bool judge_from_pre(int idx, int pre_idx) {
for(int i = 0; i < pre_num[idx]; i++) {
if(pre[idx][i] == pre_idx) return true;
}
return false;
}
void dfs(int idx, int pre_idx, int length, int head) {
if(length > ans) return;
bool from_pre = judge_from_pre(idx, pre_idx);
if(from_pre) {
for(int i = 0; i < next_num[idx]; i++) {
if(!vis[next[idx][i]]) {
vis[next[idx][i]] = true;
dfs(next[idx][i], idx, length + len[idx], head);
vis[next[idx][i]] = false;
}
else {
if(next[idx][i] != head) continue;
if(judge_from_pre(head, idx)) continue;
if(length + len[idx] < ans) ans = length + len[idx];
}
}
}
else {
for(int i = 0; i < pre_num[idx]; i++) {
if(!vis[pre[idx][i]]) {
vis[pre[idx][i]] = true;
dfs(pre[idx][i], idx, length + len[idx], head);
vis[pre[idx][i]] = false;
}
else {
if(pre[idx][i] != head) continue;
if(judge_from_pre(head, idx)) continue;
if(length + len[idx] < ans) ans = length + len[idx];
}
}
}
}
void solve() {
for(int i = 1; i <= n; i++) {
for(int j = 0; j < MAX; j++) vis[j] = false;
vis[i] = true;
dfs(i, 0, 0, i);
}
printf("%d\n", ans);
}
int main() {
freopen("fence6.in", "r", stdin);
freopen("fence6.out", "w", stdout);
init();
solve();
return 0;
}

针对一个由直线路段构成的复杂网络,通过深度优先搜索算法找出包围牧场的最小周长。该问题需处理一个无向图,每个节点代表路段,通过遍历找到最短环路。
3068

被折叠的 条评论
为什么被折叠?



