zoukankan      html  css  js  c++  java
  • uva 818 (位运算 + 判环)

     Cutting Chains 

    What a find! Anna Locke has just bought several links of chain some of which may be connected. They are made from zorkium, a material that was frequently used to manufacture jewelry in the last century, but is not used for that purpose anymore. It has its very own shine, incomparable to gold or silver, and impossible to describe to anyone who has not seen it first hand.

    Anna wants the pieces joined into a single end-to-end strand of chain. She takes the links to a jeweler who tells her that the cost of joining them depends on the number of chain links that must be opened and closed. In order to minimize the cost, she carefully calculates the minimum number of links that have to be opened to rejoin all the links into a single sequence. This turns out to be more difficult than she at first thought. You must solve this problem for her.

    Input 

    The input consists of descriptions of sets of chain links, one set per line. Each set is a list of integers delimited by one or more spaces. Every description starts with an integer n, which is the number of chain links in the set, where 1 ≤n ≤15. We will label the links 1, 2,..., n. The integers following n describe which links are connected to each other. Every connection is specified by a pair of integers i,j where 1 ≤i,j ≤n and i ≠j, indicating that chain links i and j are connected, i.e., one passes through the other. The description for each set is terminated by the pair -1 -1, which should not be processed.

    The input is terminated by a description starting with n = 0. This description should not be processed and will not contain data for connected links.

    Output 

    For each set of chain links in the input, output a single line which reads

    Set N: Minimum links to open is M

    where N is the set number and M is the minimal number of links that have to be opened and closed such that all links can be joined into one single chain.

    Sample InputOutput for the Sample Input
    5 1 2 2 3 4 5 -1 -1
    7 1 2 2 3 3 1 4 5 5 6 6 7 7 4 -1 -1
    4 1 2 1 3 1 4 -1 -1
    3 1 2 2 3 3 1 -1 -1
    3 1 2 2 1 -1 -1
    0
    
    Set 1: Minimum links to open is 1
    Set 2: Minimum links to open is 2
    Set 3: Minimum links to open is 1
    Set 4: Minimum links to open is 1
    Set 5: Minimum links to open is 1
    

    ACM World Finals 2000, Problem C

    题意好难理解,最后才弄明白原来有n个环,编号从1到n,给出了一些环环相扣的情况,比如给1和2表示1和2两个环的扣在一起的,每个环都是可以打开的,问最少打开多少个环,然后再扣好,可以让所有的环成为一条链。

    题解:

    因为n最大才15,可以用一个二进制数表示各个环是否被打开,然后未被打开的环判断一下是否还有位置度数大于2,以及是否有环的存在,并且保证打开环的数目加1要大于剩余链的数目。

    很傻的忘了环编号从1开始,wa了无数遍。。。

    #include <cstdio>
    #include <iostream>
    #include <sstream>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <string>
    #include <vector>
    #include <map>
    #include <set>
    #include <queue>
    #include <stack>
    #include <algorithm>
    using namespace std;
    #define ll long long
    #define _cle(m, a) memset(m, a, sizeof(m))
    #define repu(i, a, b) for(int i = a; i < b; i++)
    #define repd(i, a, b) for(int i = b; i >= a; i--)
    #define sfi(n) scanf("%d", &n)
    #define pfi(n) printf("%d
    ", n)
    #define sfi2(n, m) scanf("%d%d", &n, &m)
    #define pfi2(n, m) printf("%d %d
    ", n, m)
    #define pfi3(a, b, c) printf("%d %d %d
    ", a, b, c)
    #define MAXN 16
    #define R 6
    #define C 7
    const int INF = 0x3f3f3f3f;
    vector<int> v[MAXN];
    bool vis[MAXN];
    bool mp[MAXN][MAXN];
    bool open[MAXN];
    
    bool dfs(int r, int fa)
    {
        if(vis[r]) return true;
        vis[r] = 1;
        int siz = v[r].size();
        int d = siz;
        repu(i, 0, siz)
        {
            if(open[v[r][i]]) d--;
            else if(v[r][i] != fa)
                 if(dfs(v[r][i], r)) return true;
        }
        if(d > 2) return true;
        return false;
    }
    int main()
    {
        int n;
        int kase = 0;
        while(~sfi(n) && n)
        {
            kase++;
            _cle(mp, 0);
            int x, y;
            while(1)
            {
                sfi2(x, y);
                if(x == -1 && y == -1) break;
                mp[y][x] = mp[x][y] = 1;
            }
            repu(i, 1, n + 1)
            {
                v[i].clear();
                repu(j, 1, n + 1) if(mp[i][j]) v[i].push_back(j);
            }
            int minn = n;
            int lim = 1<<n;
            int flag;
            repu(i, 0, lim)
            {
                flag = 0;
                _cle(vis, 0); _cle(open, 0);
                int tot = 0, t = 0;
                repu(j, 0, n)
                  if((1<<j) & i) tot++, open[j + 1] = 1;//由于这个j + 1这我一直没加1,wa了无数遍
                repu(j, 1, n + 1)
                   if(!open[j] && !vis[j])
                   {
                       t++;
                       if(dfs(j, -1)) { flag = 1; break; }
                   }
                if(!flag && t <= tot + 1) minn = min(tot, minn);
            }
            printf("Set %d: Minimum links to open is %d
    ", kase, minn);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    滑动最小值 /// 单调队列
    Largest Rectangle in a Histogram /// 单调栈 oj23906
    能量项链 /// oj23800
    Traveling by Stagecoach /// 状压DP oj22914
    Hamilton回路 旅行商TSP问题 /// dp oj1964
    最难的工作 /// SPFA模板 oj1396
    次短路 /// dijkstra oj1597
    USACO 2006 November Gold Fence Repair /// 贪心(有意思)(优先队列) oj23940
    石子合并问题 /// 区间DP oj2025
    多边形游戏 /// 区间DP oj1903
  • 原文地址:https://www.cnblogs.com/sunus/p/4786323.html
Copyright © 2011-2022 走看看