2011-2012 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2011)Problem A Robots on a grid(迷宫dp)
程序员文章站
2022-05-24 09:16:59
...
题目链接:http://codeforces.com/gym/101555/attachments
题意:现在有一个迷宫,迷宫的图给出,首先你需要从左上角走到右下角,每次只能向下走或者向右走,问有几种走法。如果不能走到,那就四个方向随意走,问能不能从左上走到右下。
解题心得:
- 当时看见这个简单题队友就直接上了,结果敲了好一会儿敲不出来,然后看得我心急,我就自己上去敲,但是就是跑不出样例,结果发现是队友输入写错了,蜜汁尴尬的一个BUG。
- 其实做法很简单,刚开始在计算走法的时候就是一个最简单的dp,先将第一行和第一列在不遇到’#'的时候初始化为1,主要注意一下初始化和在迷宫中是否可以转移的问题。转移方程式:dp[i][j] = dp[i-1][j] + dp[i][j-1]。最后检验dp[n][n]是否不可达,如果不可达那就从左上点开始跑一个BFS就解决问题了。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1005;
typedef long long ll;
const ll mod = INT_MAX;
char mp[maxn][maxn];
ll dp[maxn][maxn];
int n, dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
bool vis[maxn][maxn];
bool checke(int x,int y) {//检验点(x, y)是否符合条件
if(x <= 0 || y <= 0 || x >n || y> n || vis[x][y] || mp[x][y] == '#')
return false;
return true;
}
void DP() {//先检验第一种走法
for (int i = 1; i <= n; i++) {
if(mp[1][i] == '.') dp[1][i] = 1;
else break;
}
for(int i=1;i<=n;i++) {
if(mp[i][1] == '.') dp[i][1] = 1;
else break;
}
for(int i=2;i<=n;i++){
for(int j=2;j<=n;j++){
if(mp[i][j] =='#') continue;
if(dp[i-1][j] + dp[i][j-1] == -2) continue;//该点无法转移到达
dp[i][j] = (max(dp[i-1][j], 0ll) + max(0ll, dp[i][j-1])) % mod;
}
}
}
bool BFS() {//第一种走法无法达到那么走bfs
queue <pair<int,int> > qu;
qu.push(make_pair(1,1));
vis[1][1] = true;
while(!qu.empty()) {
pair <int, int> now = qu.front(); qu.pop();
for(int i=0;i<4;i++) {
int nx = now.first + dir[i][0];
int ny = now.second + dir[i][1];
if(checke(nx, ny)) {
qu.push(make_pair(nx, ny));
vis[nx][ny] = true;
if(nx == n && ny == n) return true;
}
}
}
return false;
}
int main() {
// freopen("1.in","r",stdin);
scanf("%d", &n);
memset(dp, -1, sizeof dp);
for (int i = 1; i <= n; i++) scanf("%s", mp[i]+1);
DP();
if(dp[n][n] == -1) {
if(BFS()) {
printf("THE GAME IS A LIE\n");
} else {
printf("INCONCEIVABLE\n");
}
} else {
cout << dp[n][n] << endl;
}
return 0;
}