Fence Loops[USACO]

上班真无趣,还是上学好。偷偷码个题。

这个题真是让我抓狂,本来觉得很容易的(把边图转化为点图,dfs就好了)。结果在转化的时候才发现,这INPUT不是一般的恶心,后来在纸上画画,觉得不用转化应该也OK。

搞个边的结构,把所有东西都读进去。

struct SEdge
{
int nLen;
int arrSize[2];
int arrCon[2][8];
};

核心还是dfs。int dfs(int k, int pre)。k为本次处理的边,pre为上次处理的边,假设pre在k的第0组相邻边中,那么本次处理的时候从第1组中选边即可,返回本节点路径下的最小环的周长。

没有专门的剪枝...本想提交一个,看看在第几个test超时的,结果一次通过了,回头再看看标程。 

 

---------------------------------------------分割一下-----------------------------------------------

/*
ID: zhangyc1
LANG: C++
TASK: fence6
*/
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;

ofstream fileout("fence6.out");
int N;
struct SEdge 
{
    int nLen;
    int arrSize[2];
    int arrCon[2][8];
};
SEdge sEdge[101];
bool arrVisited[101];
// 路径选取到edge[i]之前历史总长度
int arrLen[101] = {0};

void prepairData()
{
    ifstream filein("fence6.in");
    filein >> N;
    int nID;
    for (int i = 1;i <= N; i++)
    {
        filein >> nID;
        filein >> sEdge[nID].nLen >> sEdge[nID].arrSize[0] >> sEdge[nID].arrSize[1];
        for (int j = 0; j < sEdge[nID].arrSize[0]; j++)
            filein >> sEdge[nID].arrCon[0][j];
        for (int j = 0; j < sEdge[nID].arrSize[1]; j++)
            filein >> sEdge[nID].arrCon[1][j];
    }
    memset(arrVisited, 0, sizeof(arrVisited));
    filein.close();
}

int dfs(int k, int pre)
{
    int nLastD = 0, nThisD = 1; // 无向有环图,初始方向无所谓,所有环在本函数中都可以遍历到
    if (pre > 0)
    {
        // 确定下次走的方向
        for (int i = 0; i < sEdge[k].arrSize[1]; i++)
        {
            if (pre == sEdge[k].arrCon[1][i])
            {
                nLastD = 1; 
                break;
            }
        }
        nThisD = 1 - nLastD;
    }
    int nMin = 25500, nCurLen = 0;
    // 延着nThisD走一条边
    arrVisited[k] = true;
    for (int i = 0; i < sEdge[k].arrSize[nThisD]; i++)
    {
        if (arrVisited[sEdge[k].arrCon[nThisD][i]]) //
        {
            nCurLen = arrLen[k] - arrLen[sEdge[k].arrCon[nThisD][i]] + sEdge[k].nLen;
        }
        else
        {
            int nTemp = arrLen[sEdge[k].arrCon[nThisD][i]];
            arrLen[sEdge[k].arrCon[nThisD][i]] = arrLen[k] + sEdge[k].nLen;
            nCurLen = dfs(sEdge[k].arrCon[nThisD][i], k);
            arrLen[sEdge[k].arrCon[nThisD][i]] = nTemp;
        }
        if (nCurLen < nMin)
        {
            nMin = nCurLen;
        }
    }
    arrVisited[k] = false;
    return nMin;
}

void process()
{
    int rs = dfs(1, -1);
    fileout << rs << endl;
}

int main(){
    prepairData();
    process();
    fileout.close();    
    return 0;
}

 

----------------------------------------------------------------------------------------------

 

Fence Loops

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.

Happily, no fence connects to itself.

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:

  • The first line of each record contains four integers: s, the segment number (1 <= s <= N); Ls, the length of the segment (1 <= Ls <= 255); N1s (1 <= N1s <= 8) the number of items on the subsequent line; and N2sthe number of items on the line after that (1 <= N2s <= 8).
  • The second line of the record contains N1 integers, each representing a connected line segment on one end of the fence.
  • The third line of the record contains N2 integers, each representing a connected line segment on the other end of the fence.

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

转载于:https://www.cnblogs.com/doublemystery/archive/2013/03/04/2943050.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值