引水入城解题报告

题目来源 NOIP2010提高组 T4;
这个题好久以前就做过了0.0当时写了个爆搜40分。今天拿出来重新做AC了。
题目太长就不在这里放出来了。这题第一问非常简单,不可能的情况写一个bfs用floodfill找一下最后一行有哪个点没有被染色即可。第二问仍然可以用BFS来做。对于1个点出发的路径,在最后一行一定会覆盖一个区间(包括只有1个点),证明如下:

如果某一个点出发的路径被分割(不为连续的区间)的话。中间那个点一定高于左右两点。然而水流流到右区间必定经过中间列,水却流不下去说明下面的高。所以这个点高于三面的点,故这种情况无法满足第二问所说的必须灌溉最后一行。所以若有第二问情况成立,则某点出发的路径在最后一行一定是一个连续不间断的区间。
这样的话,我们就把问题转化成了BFS求出线段,求最少线段覆盖区间问题。可以DP或贪心来解,DP代码如下:

#include
using namespace std;

const int MAXN=505;

struct point{
    int x,y,high;
}p[MAXN][MAXN]; 

struct xd{
    int st,js;
}xdd[MAXN];

bool cmp(xd a,xd b){
    if(a.js==b.js)return a.streturn a.js>b.js;
}

queueq;
bool vis[MAXN][MAXN];
int ax[]={0,0,1,-1},ay[]={1,-1,0,0},m,n,ans=0,dp[MAXN];

void bfs(){
    while(!q.empty()){
        point l=q.front();
        q.pop();
        for(int i=0;i<=3;i++){
            if(!vis[l.x+ax[i]][l.y+ay[i]]&&l.x+ax[i]>=1&&l.x+ax[i]<=n&&l.y+ay[i]>=1&&l.y+ay[i]<=m&&p[l.x+ax[i]][l.y+ay[i]].high1;
                q.push(p[l.x+ax[i]][l.y+ay[i]]);
            }
        }
    }
}

int main(){
    memset(vis,0,sizeof(vis));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&p[i][j].high);
            p[i][j].x=i;
            p[i][j].y=j;
        }
    }
    for(int i=1;i<=m;i++){
        if(!vis[1][i]){
            vis[1][i]=1;
            q.push(p[1][i]);
            bfs();
        }
    }
    for(int i=1;i<=m;i++){
        if(!vis[n][i])ans++;
    }
    if(ans){
        printf("0\n%d\n",ans);
        return 0;
    }
    int times=0;
    for(int i=1;i<=m;i++)
        if(p[1][i].high>=p[1][i-1].high&&p[1][i].high>=p[1][i+1].high){
            int minn=10086,maxx=-10086;
            memset(vis,0,sizeof(vis));
            vis[1][i]=1;
            q.push(p[1][i]);
            bfs();
            for(int j=1;j<=m;j++){
                if(vis[n][j]){
                    minn=min(minn,j);
                    maxx=max(maxx,j);
                }   
            }
        xdd[++times].st=minn;
        xdd[times].js=maxx; 
    }
    sort(xdd+1,xdd+1+times,cmp);
    int answer=0x7fffffff;
    memset(dp,0x7f,sizeof(dp));
    dp[1]=1;
    for(int i=2;i<=times;i++){
        for(int j=1;jif(xdd[i].js>=xdd[j].st-1)dp[i]=min(dp[i],dp[j]+1);
        }
    }
    for(int i=1;i<=times;i++){
        if(xdd[i].st==1)answer=min(answer,dp[i]);
    }
    printf("1\n%d",answer);
    return 0;
}

你可能感兴趣的:(DP,BFS)