zoukankan      html  css  js  c++  java
  • BZOJ2595: [Wc2008]游览计划(斯坦纳树,状压DP)

    Time Limit: 10 Sec  Memory Limit: 256 MBSec  Special Judge
    Submit: 2030  Solved: 986
    [Submit][Status][Discuss]

    Description

    Input

    第一行有两个整数,N和 M,描述方块的数目。 
    接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个景点;
    否则表示控制该方块至少需要的志愿者数目。 相邻的整数用 (若干个) 空格隔开,
    行首行末也可能有多余的空格。

    Output


    由 N + 1行组成。第一行为一个整数,表示你所给出的方案
    中安排的志愿者总数目。 
    接下来 N行,每行M 个字符,描述方案中相应方块的情况: 
    z  ‘_’(下划线)表示该方块没有安排志愿者; 
    z  ‘o’(小写英文字母o)表示该方块安排了志愿者; 
    z  ‘x’(小写英文字母x)表示该方块是一个景点; 
    注:请注意输出格式要求,如果缺少某一行或者某一行的字符数目和要求不
    一致(任何一行中,多余的空格都不允许出现) ,都可能导致该测试点不得分。

    Sample Input

    4 4
    0 1 1 0
    2 5 5 1
    1 5 5 1
    0 1 1 0



    Sample Output

    6
    xoox
    ___o
    ___o
    xoox

    HINT

     对于100%的数据,N,M,K≤10,其中K为景点的数目。输入的所有整数均在[0,2^16]的范围内

    Source

     
    很明显是斯坦纳树
    $f[i][j][sta]$表示$(i,j)$这个位置,与其他景点的连通性为$sta$时的最小花费
    转移的时候一种是枚举子集
    另一种是spfa判断,
    比较套路
     
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    const int limit = 1050;
    const int INF = 1e9;
    inline int read() {
        char c = getchar(); int x = 0, f = 1;
        while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
        while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
        return x * f;
    }
    #define MP(i,j) make_pair(i,j)
    #define se second
    #define fi first
    #define Pair pair<int,int>
    int N, M, tot = 0;
    int a[12][12], f[12][12][limit];
    int xx[5] = {-1, +1, 0, 0};
    int yy[5] = {0, 0, -1, +1};
    int vis[12][12];
    struct PRE {
        int x, y, S;
    }Pre[12][12][limit];
    queue<Pair>q;
    void SPFA(int cur) {
        while(q.size() != 0) {
            Pair p = q.front();q.pop();
            vis[p.fi][p.se] = 0;
            for(int i = 0; i <4; i++) {
                int wx = p.fi + xx[i], wy = p.se + yy[i];
                if(wx < 1 || wx > N || wy < 1 || wy > M) continue;
                if(f[wx][wy][cur] > f[p.fi][p.se][cur] + a[wx][wy]) {
                    f[wx][wy][cur] = f[p.fi][p.se][cur] + a[wx][wy];
                    Pre[wx][wy][cur] = (PRE){p.fi, p.se, cur};
                    if(!vis[wx][wy])
                        vis[wx][wy] = 1, q.push(MP(wx,wy));
                }
            }
        }
    }
    void dfs(int x, int y, int now) {
        vis[x][y] = 1;
        PRE tmp = Pre[x][y][now];
        if(tmp.x == 0 && tmp.y == 0) return;
        dfs(tmp.x, tmp.y, tmp.S);
        if(tmp.x == x && tmp.y == y) dfs(tmp.x, tmp.y, now - tmp.S);
    }
    int main() {
        N = read(); M = read();
        memset(f, 0x3f, sizeof(f));
        for(int i = 1; i <= N; i++)
            for(int j = 1; j <= M; j++) {
                a[i][j] = read();
                if(a[i][j] == 0)
                    f[i][j][1 << tot] = 0, tot++;
            }
        int limit = (1 << tot) - 1;
        for(int sta = 0; sta <= limit; sta++) {
            for(int i = 1; i<= N; i++)
                for(int j = 1; j <= M;j++) {
                    for(int s = sta & (sta - 1); s; s = (s - 1) & sta) {
                        if(f[i][j][s] + f[i][j][sta - s] - a[i][j] < f[i][j][sta])
                            f[i][j][sta] = f[i][j][s] + f[i][j][sta - s] - a[i][j],
                            Pre[i][j][sta] = (PRE){i,j,s};
                    }
                    if(f[i][j][sta] < INF) q.push(MP(i,j)), vis[i][j] = 1;
                }
            SPFA(sta);
        }
        int ansx, ansy, flag = 0;
        for(int i = 1; i <= N && !flag; i++)
            for(int j = 1; j <= M; j++)
                if(!a[i][j]) 
                    {ansx = i, ansy = j; flag = 1; break;}
        printf("%d
    ",f[ansx][ansy][limit]); 
        memset(vis, 0, sizeof(vis));
        dfs(ansx, ansy, limit);
        for(int i = 1; i <= N; i++, puts("")) {
            for(int j = 1; j <= M; j++) {
                if(a[i][j] == 0) putchar('x');
                else if(vis[i][j]) putchar('o');
                else putchar('_');            
            } 
        } 
        return 0;
    }
  • 相关阅读:
    python class属性
    获取安卓系统日志输出
    深入理解C#中的IDisposable接口(转)
    Mac开启自带的Apache服务器
    【转】《Unity Shader入门精要》冯乐乐著 书中彩图
    AssetDatabase的方法总结
    C# 读写XML文件的方法
    tkinter模块常用参数(python3)
    Unity在Project视图里面显示文件的拓展名
    Git忽略提交规则
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/8976814.html
Copyright © 2011-2022 走看看