P1514 引水入城 (记忆化搜索 + 区间覆盖

#include 
using namespace std;
using VI = vector;
using PII = pair;
using ll = long long;
int n,t,m;
int l[510][510];
int r[510][510];
int a[510][510];
int vis[510][510];
int dx[] = {1,0,-1,0};
int dy[] = {0,1,0,-1};
void dfs(int x,int y){
    vis[x][y] = 1;
    for(int i=0;i<4;i++){
        int xx = x + dx[i];
        int yy = y + dy[i];
        if(xx >= 1 && xx <= n && yy >= 1 && yy <= m && a[x][y] > a[xx][yy]){
            if(!vis[xx][yy]) dfs(xx,yy);
            l[x][y] = min(l[x][y] , l[xx][yy]);
            r[x][y] = max(r[x][y] , r[xx][yy]);
        }

    }
}

int main(){
    cin>>n>>m;
    memset(l,0x3f,sizeof l);
    memset(r,0,sizeof r);

    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>a[i][j];
        }
    }
    for(int i=1;i<=m;i++){
        l[n][i] = r[n][i] = i;
    }
    for(int i=1;i<=m;i++){
        if(!vis[1][i]) dfs(1,i);
        //cout< range;
    for(int i=1;i<=m;i++){
        if(!vis[n][i]) tot++;
        else{
            range.push_back({l[1][i],r[1][i]});
        }
    }

    sort(range.begin(),range.end());
    if(tot){
        printf("0\n");
        printf("%d",tot);
        return 0;
    }
    int s = 1;
    for(int i=0;i= m){
            cout<<1<

记忆化搜索的本质上其实是dp,当前的解与后续的解有转移方程,于是就记录每个位置的解,避免重复的搜索

——————————————————

区间覆盖是把左端点排序,按照顺序取出满足左端点pos <= start 中right 最大的点,

然后更新区间(start,end)->(right,end)  当right>=end是就输出

你可能感兴趣的:(搜索,图论,深度优先,算法)