15Y。。。不过离当时的 hdu4766 21Y还有一段距离。。。
刚开始拿到这题就直接bfs搞 TLE了一发。。。然后发现图中那些空地是可有可无的,于是可以把图中所有F G Y抽象出来建图,然后bfs。这个思路基本正解了吧?
于是就wa了一整晚。。。拉着lyj yy了一晚上,总觉得bfs是可以转移所有状态的。。。但是就是wa到死。。。
然后就发现了网上的人都是用dp来完成状态转移的。。为什么bfs不能。。。(事实证明是我的bfs写挫了。。。)搞了个dp解法,然后就AC了。。。
即使就这么AC了,还是很不爽,心里还在怨念bfs。。。如果bfs搞不出来,那dfs呢。。。于是又搞了个dfs。。。。62ms。。无语了。。。
博客第100题来的如此艰难。。。撸完这题,apm++。。。
//用dp判断二分答案是否合法 390ms #include<algorithm> #include<iostream> #include<cstring> #include<fstream> #include<sstream> #include<cstdlib> #include<vector> #include<string> #include<cstdio> #include<bitset> #include<queue> #include<stack> #include<cmath> #include<map> #include<set> #define FF(i, a, b) for(int i=a; i<b; i++) #define FD(i, a, b) for(int i=a; i>=b; i--) #define REP(i, n) for(int i=0; i<n; i++) #define CLR(a, b) memset(a, b, sizeof(a)) #define debug puts("**debug**") #define LL long long #define PB push_back #define MP make_pair using namespace std; const int maxn = 20; char g[maxn][maxn]; int n, m, S, tot, all, gank, goal, id[maxn], dist[maxn][maxn]; bool vis[maxn][maxn]; map<int, int> mp, mp1; map<int, char> mp2; struct Node { int u, steps; Node(){} Node(int a, int b) :u(a), steps(b){} }; int dx[4] = {0, 0, 1, -1}; int dy[4] = {1, -1, 0, 0}; void bfs(int u) { queue<Node> q; q.push(Node(u, 0)); int xx = u/100, yy = u%100; CLR(vis, 0); vis[xx][yy] = 1; while(!q.empty()) { Node T = q.front(); q.pop(); REP(i, 4) { int tx = T.u/100 + dx[i], ty = T.u%100 + dy[i]; if(tx<0 || tx>=n || ty<0 || ty>=m) continue; if(vis[tx][ty] || g[tx][ty] == 'D') continue; vis[tx][ty] = 1; q.push(Node(tx*100+ty, T.steps+1)); if(g[tx][ty] != 'S') { int v = mp1[tx*100+ty]; dist[mp1[u]][v] = dist[v][mp1[u]] = T.steps+1; } } } return ; } void init() { tot = goal = 0; CLR(dist, -1); mp.clear(); mp1.clear(); mp2.clear(); } void build() { REP(i, n) { scanf("%s", g[i]); REP(j, m) { if(g[i][j] == 'F') id[tot] = 1, S = tot, mp2[tot] = g[i][j], mp[tot] = i*100+j, mp1[i*100+j] = tot++; else if(g[i][j] == 'G') mp2[tot] = g[i][j], id[tot] = 2, mp[tot] = i*100+j, mp1[i*100+j] = tot++; else if(g[i][j] == 'Y') goal |= 1<<tot, mp2[tot] = g[i][j], id[tot] = 3, mp[tot] = i*100+j, mp1[i*100+j] = tot++; } } all = (1<<tot); REP(i, tot) bfs(mp[i]); } int dp[15][1<<15]; bool ok(int mid) { CLR(dp, -1); dp[S][1<<S] = mid; REP(s, all) REP(u, tot) if(dp[u][s] != -1 && (s & (1<<u))) { if((s & goal) == goal) return true; REP(v, tot) if(dist[u][v] > 0) { if(s & (1<<v)) continue; if(dp[u][s] < dist[u][v]) continue; int sta = s | (1<<v); if(dp[v][sta] == -1 || dp[v][sta] < dp[u][s] - dist[u][v]) dp[v][sta] = dp[u][s] - dist[u][v]; if(mp2[v] == 'G') dp[v][sta] = mid; } } return false; } void solve() { REP(i, tot) if(i != S) { if(mp2[i] == 'Y' && dist[S][i] < 0) { puts("-1"); return ; } } int L = 0, R = 2*n*m, M, ans = -1; while(L <= R) { M = (L + R) >> 1; if(ok(M)) ans = M, R = M - 1; else L = M + 1; } printf("%d\n", ans); } int main() { //freopen("input.txt", "r", stdin); //freopen("output.txt", "r", stdout); while(scanf("%d%d", &n, &m), n+m) { init(); build(); solve(); } return 0; }
//dfs爆搞 62ms。。。。 #include<algorithm> #include<iostream> #include<cstring> #include<fstream> #include<sstream> #include<cstdlib> #include<vector> #include<string> #include<cstdio> #include<bitset> #include<queue> #include<stack> #include<cmath> #include<map> #include<set> #define FF(i, a, b) for(int i=a; i<b; i++) #define FD(i, a, b) for(int i=a; i>=b; i--) #define REP(i, n) for(int i=0; i<n; i++) #define CLR(a, b) memset(a, b, sizeof(a)) #define debug puts("**debug**") #define LL long long #define PB push_back #define MP make_pair using namespace std; const int maxn = 20; char g[maxn][maxn]; int n, m, S, tot, all, gank, goal, id[maxn], dist[maxn][maxn]; bool vis[maxn][maxn]; map<int, int> mp, mp1; map<int, char> mp2; struct Node { int u, steps; Node(){} Node(int a, int b) :u(a), steps(b){} }; int dx[4] = {0, 0, 1, -1}; int dy[4] = {1, -1, 0, 0}; void bfs(int u) { queue<Node> q; q.push(Node(u, 0)); int xx = u/100, yy = u%100; CLR(vis, 0); vis[xx][yy] = 1; while(!q.empty()) { Node T = q.front(); q.pop(); REP(i, 4) { int tx = T.u/100 + dx[i], ty = T.u%100 + dy[i]; if(tx<0 || tx>=n || ty<0 || ty>=m) continue; if(vis[tx][ty] || g[tx][ty] == 'D') continue; vis[tx][ty] = 1; q.push(Node(tx*100+ty, T.steps+1)); if(g[tx][ty] != 'S') { int v = mp1[tx*100+ty]; dist[mp1[u]][v] = dist[v][mp1[u]] = T.steps+1; } } } return ; } void init() { tot = goal = 0; CLR(dist, -1); mp.clear(); mp1.clear(); mp2.clear(); } void build() { REP(i, n) { scanf("%s", g[i]); REP(j, m) { if(g[i][j] == 'F') id[tot] = 1, S = tot, mp2[tot] = g[i][j], mp[tot] = i*100+j, mp1[i*100+j] = tot++; else if(g[i][j] == 'G') mp2[tot] = g[i][j], id[tot] = 2, mp[tot] = i*100+j, mp1[i*100+j] = tot++; else if(g[i][j] == 'Y') goal |= 1<<tot, mp2[tot] = g[i][j], id[tot] = 3, mp[tot] = i*100+j, mp1[i*100+j] = tot++; } } all = (1<<tot); REP(i, tot) bfs(mp[i]); } bool see[20]; bool dfs(int u, int res, int sta, int mid) { if((sta&goal) == goal) return true; REP(v, tot) if(dist[u][v] > 0) { if(see[v] || res < dist[u][v]) continue; if(mp2[v] == 'G') { see[v] = 1; if(dfs(v, mid, sta|(1<<v), mid)) return true; see[v] = 0; } else { see[v] = 1; if(dfs(v, res-dist[u][v], sta|(1<<v), mid)) return true; see[v] = 0; } } return false; } bool ok(int mid) { CLR(see, 0); see[S] = 1; return dfs(S, mid, 1<<S, mid); } void solve() { REP(i, tot) if(i != S) { if(mp2[i] == 'Y' && dist[S][i] < 0) { puts("-1"); return ; } } int L = 0, R = 2*n*m, M, ans = -1; while(L <= R) { M = (L + R) >> 1; if(ok(M)) ans = M, R = M - 1; else L = M + 1; } printf("%d\n", ans); } int main() { //freopen("input.txt", "r", stdin); //freopen("output.txt", "r", stdout); while(scanf("%d%d", &n, &m), n+m) { init(); build(); solve(); } return 0; }