记忆化搜索 get !

· · 个人记录

简单:

传送门

一遍切黄!

话说省选题为什么这么简单

#define int long long
int cnt,n,m;
int head[4*MAXN],in[MAXN],out[MAXN];
int dp[MAXN];

int dfs(int u)
{
    int ans = 0;
    if(dp[u]) return dp[u];
    if(in[u] && !out[u]) return dp[u] = 1;
    for(int k=head[u];k;k=map[k].next)
    {
        int v = map[k].to;
        dp[u] += dfs(v);
    }
    return dp[u];
}

signed main(void)
{
    cin >> n >> m;
    for(int i=1,u,v;i<=m;i++)
    {
        cin >> u >> v;
        out[u]++;in[v]++;
        add(u,v);
    }
    int ans = 0;
    for(int i=1;i<=n;i++)
        if(!in[i]) ans += dfs(i);
    cout << ans;
}

填坑:

传送门

这道题由于不好 DP ,所以采用记忆化搜索。

记录每个点向左右最远能到哪,

如果最后一行有未访问的点,输出 0

否则找最少建几个蓄水厂,

怎么找呢?

枚举一个左端点 L 如果某点最左能达到 L 的左边,

显然 L 左边的点也可以连通该点所能到的点,

所以用 R 记录该点的最右,更新 L 为 R+1 ,

即由于在之前的点最右也是小于 R+1 的,所以要新建一个厂

int maxL[MAXN][MAXN];   //最大能达到的左端点
int maxR[MAXN][MAXN];               //右端点
int vis[MAXN][MAXN];
int fx[4] = {0,0,-1,1};
int fy[4] = {1,-1,0,0};

void dfs(int x, int y)
{
    vis[x][y] = 1;
    for(int i=0;i<4;i++)
    {
        int nx = x+fx[i];
        int ny = y+fy[i];
        if(nx<1 || ny<1 || nx>n || ny>m)continue;
        if(map[nx][ny] >= map[x][y])    continue;
        if(!vis[nx][ny])    dfs(nx,ny);
        maxL[x][y] = min(maxL[x][y],maxL[nx][ny]);
        maxR[x][y] = max(maxR[x][y],maxR[nx][ny]);
    }
}

int main(void)
{
    memset(maxL,0x3f,sizeof maxL);
    cin >> n >> m;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
        cin >> map[i][j];
    for(int i=1;i<=m;i++)
        maxL[n][i] = maxR[n][i] = i;
    for(int i=1;i<=m;i++)
        if(!vis[1][i])  dfs(1,i);
    for(int i=1;i<=m;i++)
        if(!vis[n][i])
        {
            ans++;
            flag = 1;
        }
    if(flag)
    {
        cout << "0" << endl << ans;
        return 0;
    }
    int R = 1,L = 1;
    while(L <= m)
    {
        for(int i=L;i<=m;i++)
        {
            if(maxL[1][i] <= L)
                R = max(R,maxR[1][i]);
            else    break;
        }
        L = R+1;
        ans++;
    }
    cout << "1" << endl << ans;
    return 0;
}