牛客小白月赛27 C
分析
对于这张图的关键点非常少,对于每一个点对我们可以求出之间的距离,我们考虑状压转移。 ,表示节点 为根节点,已经走过的节点集合为 所需要的最小步数。总的复杂度为 , 表示有多少个坏掉的电线杆。
代码
#include<bits/stdc++.h> using namespace std; const int N = 210,inf = 0x3f3f3f3f; #define LL long long struct Node{int x,y;}p[21]; int vis[N][N]; int dp[N][101000];int n,m,t,top,f[21][21]; char ch[N][N]; int dx[4] = {0,0,-1,1},dy[4] = {1,-1,0,0}; void solve(int id) { memset(vis,inf,sizeof(vis));vis[p[id].x][p[id].y] = 0; queue<Node> q;q.push((Node){p[id].x,p[id].y}); while(q.size()) { Node x = q.front();q.pop(); for(int i = 0;i < 4;i++) { int X = x.x + dx[i],Y = x.y + dy[i]; if(vis[X][Y] != inf||X < 1||Y < 1||X > n||Y > m||ch[X][Y] == '#') continue; vis[X][Y] = vis[x.x][x.y] + 1; q.push((Node){X,Y}); } } } int main() { cin >> n >> m >> t; int sx,sy; for(int i = 1;i <= n;i++) { for(int j = 1;j <= m;j++) { cin >> ch[i][j]; if(ch[i][j] == 'S') sx = i,sy = j; if(ch[i][j] == 'T') p[++top] = (Node){i,j}; } } p[++top] = (Node){sx,sy}; for(int i = 1;i <= top;i++) { solve(i); for(int j = 1;j <= top;j++) { f[i][j] = vis[p[j].x][p[j].y]; } } memset(dp,0x3f,sizeof(dp)); dp[top][1<<top-1] = 0; for(int s = 1;s < (1<<top);s++) { for(int j = 1;j <= top;j++) { if(((s>>j-1)&1) && dp[j][s] != inf) { for(int i = 1;i <= top;i++) { if((s>>i-1)&1) continue; dp[i][(s|(1<<i-1))] = min(dp[j][s] + f[j][i],dp[i][s|(1<<i-1)]); } } } } int ans = inf; for(int i = 1;i <= top;i++) ans = min(ans,dp[i][(1<<top)-1] + f[i][top]); if(ans == inf) cout << "-1" << endl; else cout << ans + 1LL * (top-1) * t << endl; return 0; }