[NOIP2010]引水入城

来源:互联网 发布:爱剪辑软件 编辑:程序博客网 时间:2024/04/27 18:50

传送门
思路:拿到这道题我就开始想不到正解就开始应该怎么搜(汗),不过还是好,能拿到70分(因为我舍弃了一种情况,就是从一个蓄水站往下走到另外一个沿湖城市,这种搜了很花时间)。听到正解发现我的思路真是不够,真是不行,我们可以发现每一个沿海城市能够到达的城市是连续的,所以我们就可以用一个N³搜索将原问题转化为一个区间覆盖问题,然后就可以水过了。

代码:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define MAXN 250005#define MAXM 1000005int dd[4][2] = {0,1,0,-1,1,0,-1,0};int mp[505][505], sx[505][505], sy[505][505], I, ld[505], rd[505], n, m;int col[505];bool vis[505][505];bool dfs(int x, int y){    if(vis[x][y] && x != 1) return sx[x][y];    vis[x][y] = 1;    if(x == 1) return 1;    for(int i = 0; i < 4; i ++)    {        int tx = x + dd[i][0], ty = y + dd[i][1];        if(tx < 1 || tx > n || ty > m || ty < 1) continue;        if(mp[tx][ty] > mp[x][y]) if(dfs(tx, ty)) {sx[x][y] = tx, sy[x][y] = ty; break;}    }    return sx[x][y];}int ans = 0x3f3f3f3f;struct E{    int l, r;    bool operator < (const E rhs) const    {        return l < rhs.l;    }}e[505];int L, R, cnt, dp[505];void dfs1(int x, int y){    if(x == n)    {        if(L > y) L = y;        if(R < y) R = y;    }    for(int i = 0; i < 4; i ++)    {        int tx = x + dd[i][0], ty = y + dd[i][1];        if(tx < 1 || tx > n || ty > m || ty < 1) continue;        if(mp[tx][ty] < mp[x][y]) dfs1(tx, ty);    }    return;}int main(){    scanf("%d%d", &n, &m);    for(int i = 1; i <= n; i ++)        for(int j = 1; j <= m; j ++)            scanf("%d", &mp[i][j]);    if(n == 1)    {        int answer = 0;        for(int i = 1; i <= m; i ++)            if(mp[1][i] >= mp[1][i-1] && mp[1][i] >= mp[1][i+1]) answer ++;        printf("1\n%d\n", answer);        return 0;    }    int flag = 0;    for(int i = 1; i <= m; i ++)        if(dfs(n, i)) flag ++;    if(flag != m)    {        printf("0\n%d\n", m - flag);        return 0;    }    for(int i = 1; i <= m; i ++)    {        L = 505, R = -1;        dfs1(1, i);        if(R != -1) {e[++ cnt].l = L;e[cnt].r = R;}    }    memset(dp, 0x3f, sizeof dp);    dp[0] = 0;    for(int i = 1; i <= m; i ++)        for(int j = 1; j <= cnt; j ++)            if(i >= e[j].l && i <= e[j].r && dp[i] > dp[e[j].l-1] + 1)                dp[i] = dp[e[j].l-1] + 1;    printf("1\n%d\n", dp[m]);    return 0;}
0 0
原创粉丝点击