传送门
思路:拿到这道题我就开始想不到正解就开始应该怎么搜(汗),不过还是好,能拿到70分(因为我舍弃了一种情况,就是从一个蓄水站往下走到另外一个沿湖城市,这种搜了很花时间)。听到正解发现我的思路真是不够,真是不行,我们可以发现每一个沿海城市能够到达的城市是连续的,所以我们就可以用一个N³搜索将原问题转化为一个区间覆盖问题,然后就可以水过了。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 250005
#define MAXM 1000005
int 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;
}