zoukankan      html  css  js  c++  java
  • POJ1062 昂贵的聘礼 区间枚举

    第二次来做这一题,由于题目中给定了一个等级限制M,所以可以通过枚举第一个点所在的位置求解.思路很清晰.

    for (int i = 0; i <= M; ++i) 这个i来表示第一个点的等级在M长度区间内的偏移量.然后再在区间内建边,floyd即可.

    代码如下:

    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #define INF 0x3f3f3f3f
    using namespace std;
    
    int M, N, mey[105], lvl[105], head[105], idx;
    
    int lwall, rwall, G[105][105];
    
    struct Edge {
        int v, val, next;
    }e[10005]; // 保留替换列表 
    
    void addedge(int x, int v, int val) {
        ++idx;
        e[idx].v = v, e[idx].val = val;
        e[idx].next = head[x], head[x] = idx;
    }
    
    inline bool in(int x) {
        if (lvl[x] >= lwall && lvl[x] <= rwall) {
            return true;    
        } else return false;
    }
    
    void build() {
        memset(G, 0x3f, sizeof (G));
        for (int i = 1; i <= N; ++i) {
            G[i][i] = 0;
            for (int j = head[i]; j != -1; j = e[j].next) {
                if (in(i) && in(e[j].v)) {
                    G[i][e[j].v] = e[j].val;
                }
            }    
        }
    }
    
    void floyd(int &ret) {
        for (int k = 1; k <= N; ++k) {
            for (int i = 1; i <= N; ++i) {
                for (int j = 1; j <= N; ++j) {
                    if (G[i][k]!=-1&&G[k][j]!=-1) { // 有边相连 
                        G[i][j] = min(G[i][j], G[i][k]+G[k][j]);
                    }
                }    
            }    
        }
        for (int i = 1; i <= N; ++i) {
            if (G[1][i] != INF) {
                ret = min(ret, G[1][i]+mey[i]);
            }
        }
    }
    
    int main() {
        int c, v, val, ret;
        while (scanf("%d %d", &M, &N) == 2) {
            ret = INF;
            idx = -1;
            memset(head, 0xff, sizeof (head));
            for (int i = 1; i <= N; ++i) {
                scanf("%d %d %d", &mey[i], &lvl[i], &c);
                for (int j = 1; j <= c; ++j) {
                    scanf("%d %d", &v, &val);
                    addedge(i, v, val);
                }
            }
            // 通过枚举第一个点在M区间的最左边和最右边 
            for (int i = 0; i <= M; ++i) {
                lwall = lvl[1]-i, rwall = lwall+M;
                if (lwall < 0) break; // 左边界不可能为负数 
                // 确定好了左右界在进行构边
                build();
                floyd(ret);
            }
            printf("%d\n", ret);
        }
        return 0;    
    }
  • 相关阅读:
    qt运行编译按钮居然是灰色的
    suse linux服务器的常用命令
    windows 防火墙的bug
    烦恼核心
    System.Data.OleDb.OleDbException (0x80004005) 的问题
    c#利用批处理清理大目录
    Spider Studio 社区信息
    示例
    示例
    Spider Studio 新版本 (20140225)
  • 原文地址:https://www.cnblogs.com/Lyush/p/2695434.html
Copyright © 2011-2022 走看看