先预处理出每个通道的终点到其他通道的起点的最短路,然后和 HDOJ 3247 Resource Archiver 一样,用个状态压缩DP三重循环就好了。。。顺便写了一个数据生成器,方便读者debug。。。
#include <iostream> #include <sstream> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <climits> #define maxn 100005 #define eps 1e-6 #define mod 10007 #define INF 99999999 #define lowbit(x) (x&(-x)) //#define lson o<<1, L, mid //#define rson o<<1 | 1, mid+1, R typedef long long LL; using namespace std; char g[20][20]; int sx[20], sy[20], ex[20], ey[20]; int dis[20][20]; int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; int vis[20][20]; int d[20][20]; int dp[maxn][20]; struct node { int x, y; int step; }tmp, now; queue<node> q; int n, m; void bfs(int x) { int i, j; tmp.x = ex[x], tmp.y = ey[x], tmp.step = 0; q.push(tmp); memset(vis, 0, sizeof vis); vis[tmp.x][tmp.y] = 1; for(i = 1; i <= n; i++) for(j = 1; j <= n; j++) d[i][j] = INF; d[tmp.x][tmp.y] = 0; while(!q.empty()) { now = q.front(); q.pop(); for(i = 0; i < 4; i++) { tmp.x = now.x + dir[i][0]; tmp.y = now.y + dir[i][1]; if(g[tmp.x][tmp.y] == '.' && !vis[tmp.x][tmp.y]) { q.push(tmp); d[tmp.x][tmp.y] = d[now.x][now.y] + 1; vis[tmp.x][tmp.y] = 1; } } } for(i = 1; i <= m; i++) dis[x][i] = d[sx[i]][sy[i]]; dis[x][x] = 0; } void init(void) { memset(dis, 0, sizeof dis); memset(g, '#', sizeof g); } void read(void) { int i; for(i = 1; i <= n; i++) scanf("%s", g[i]+1), g[i][n+1] = '#'; for(i = 1; i <= m; i++) scanf("%d%d%d%d", &sx[i], &sy[i], &ex[i], &ey[i]); } void work(void) { int i, j, k, ans; for(i = 1; i <= m; i++) bfs(i); for(i = 0; i < (1<<m); i++) for(j = 1; j <= m; j++) dp[i][j] = INF; for(i = 0; i < m; i++) dp[1<<i][i+1] = 0; for(i = 0; i < (1<<m); i++) for(j = 1; j <= m; j++) if(dp[i][j] != INF) for(k = 1; k <= m; k++) if(dis[j][k] != INF && !(i&(1<<(k-1))) ) dp[i | (1<<(k-1))][k] = min(dp[i | (1<<(k-1))][k], dp[i][j] + dis[j][k]); ans = INF; for(i = 1; i <= m; i++) ans = min(ans, dp[(1<<m)-1][i]); if(ans != INF) printf("%d\n", ans); else printf("-1\n"); } int main(void) { while(scanf("%d%d", &n, &m)!=EOF) { init(); read(); work(); } return 0; }
#include <iostream> #include <sstream> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <climits> #include <time.h> #define maxn 60000 #define eps 1e-6 #define mod 10007 #define INF 99999999 #define lowbit(x) ((x)&(-(x))) #define lson o<<1, L, mid #define rson o<<1 | 1, mid+1, R typedef long long LL; using namespace std; char g[20][20]; int main(void) { //freopen ( "out.txt" , "w" , stdout ) ; int n, m, i, tmp1, tmp2, tmp3, tmp4, cnt, tmp, j; srand(time(NULL)); for ( int _ = 1 ; _ <= 10 ; ++ _ ) { n = rand () % 15 + 1 ; m = rand () % 15 + 1 ; printf("%d %d\n", n, m); for(i = 1; i <= n; i++) { cnt = 1; while(cnt<=n) { tmp = rand()%2; if(tmp) g[i][cnt++] = '.'; else g[i][cnt++] = '#'; } } for(i = 1; i <= n; i++) { for(j = 1; j <= n; j++) printf("%c", g[i][j]); printf("\n"); } for(i = 1; i <= m; i++) { tmp1 = rand()%n+1; tmp2 = rand()%n+1; tmp3 = rand()%n+1; tmp4 = rand()%n+1; while(g[tmp1][tmp2] != '.' || g[tmp3][tmp4] != '.') { tmp1 = rand()%n+1; tmp2 = rand()%n+1; tmp3 = rand()%n+1; tmp4 = rand()%n+1; } printf("%d %d %d %d\n", tmp1, tmp2, tmp3, tmp4); } } }