Luogu 1514 [NOIP2010] 引水入城

我就是过来开心一下……这道题从开坑以来已经堆积了大半年了……今天才发现广搜一直写挂……

丢个线段覆盖的模板,设$f_{i}$表示覆盖区间[1, i]的最小代价,$g_{i, j}$表示覆盖区间[i, j]的代价,有转移方程

                              $f_{i} = f_{j} + g_{j + 1, i}$   $(0 < j < i)$

这道题直接暴力跑转移就可以了,但是对于一些n比较大的题,可以写一个前向星或者是vector存右端点一样的线段,这样子会快很多

还有要注意n = 1的坑点

放个提交记录给自己警示一下!https://www.luogu.org/recordnew/lists?uid=60553&pid=1514

Code:

#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;

const int N = 505;
const int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, 1, -1};
const int inf = 0x3f3f3f3f; 

int n, m, a[N][N], f[N], g[N][N], ran[N][2], tot = 0, head[N];
bool cov[N], vis[N], vis2[N][N];

struct Segment {
    int ln, nxt;
} s[N];

inline void add(int ln, int rn) {
    s[++tot].ln = ln;
    s[tot].nxt = head[rn];
    head[rn] = tot;
}

inline void read(int &X) {
    X = 0;
    char ch = 0;
    int op = 1;
    for(; ch > '9' || ch < '0'; ch = getchar())
        if(ch == '-') op = -1;
    for(; ch >= '0' && ch <= '9'; ch = getchar())
        X = (X << 3) + (X << 1) + ch - 48;
    X *= op;
}

inline int max(int x, int y) {
    return x > y ? x : y;
}

inline int min(int x, int y) {
    return x > y ? y : x;
}

struct Node {
    int x, y;
};
queue <Node> Q;

inline bool vivid(Node now) {
    return now.x >= 1 && now.x <= n && now.y >= 1 && now.y <= m;
}

void bfs(int fir) {    
    memset(vis2, 0, sizeof(vis2));
    vis2[1][fir] = 1;
    int ln = inf, rn = -inf;
    Q.push((Node) {1, fir});
    if(n == 1) {
        cov[fir] = 1;
        ln = rn = fir;
    }
    
    vis[fir] = 1;
    
    for(; !Q.empty(); ) {
        Node out = Q.front(); Q.pop();
        for(int i = 0; i < 4; i++) {
            Node in = (Node) {out.x + dx[i], out.y + dy[i]};
            if(vivid(in) && a[out.x][out.y] > a[in.x][in.y] && !vis2[in.x][in.y]) {
                if(in.x == 1) vis[in.y] = 1;
                if(in.x == n) {
                    cov[in.y] = 1;
                    ln = min(ln, in.y);
                    rn = max(rn, in.y);
                }
                vis2[in.x][in.y] = 1;
                Q.push(in);
            }
        } 
    }
//    printf("%d %d %d\n", fir, ln, rn);
    if(ln > rn) return;
    
    for(int i = ln; i <= rn; i++) {
        for(int j = i; j <= rn; j++) {
            g[i][j] = 1;
            if(i == 1) f[j] = 1;
        }
    }
}

int main() {
//    freopen("1.in", "r", stdin); 
    
    read(n), read(m);
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            read(a[i][j]);
    memset(g, 0x3f, sizeof(g));
    memset(f, 0x3f, sizeof(f));
    for(int i = 1; i <= m; i++) 
        if(!vis[i]) bfs(i);
        
    int cnt = 0;
    for(int i = 1; i <= m; i++) 
        if(!cov[i]) cnt++;
        
    if(cnt > 0) {
        printf("0\n%d\n", cnt);
        return 0;
    }
    
/*    for(int i = 1; i <= m; i++)
        printf("%d ", f[i]);
    printf("\n");   */
    
    for(int i = 1; i <= m; i++)
        for(int j = 1; j <= i; j++) 
            f[i] = min(f[i], f[j] + g[j + 1][i]);
    printf("1\n%d\n", f[m]);
    
    return 0;
}

 

posted @ 2018-08-13 18:43  CzxingcHen  阅读(121)  评论(0编辑  收藏  举报