https://ac.nowcoder.com/acm/contest/318/H
 
C++版本一
 題解:直接bfs,對每個狀態(tài)記錄一下他收集了那些快樂水。記錄狀態(tài)有一個小技巧,二進制壓縮記錄狀態(tài)。(自己百度狀壓去)用3位二進制數(shù)記錄你獲得了那些快樂水。栗子:000表示你有0瓶快樂水,001表示你有第一瓶快樂水,110表示你有第二,三瓶快樂水,依次類推。一共有8個狀態(tài)0-7,用vis[state][x][y]表示你從起點到達(x,y)位置且狀態(tài)為sta的最小消耗。注意,當你經(jīng)過快樂水的節(jié)點你可以選擇撿起或不撿起來。
 Ps:細節(jié)見代碼,當然自己補題更好。
 
#include<bits/stdc++.h>
#define mme(a,b) memset((a),(b),sizeof((a)))
#define fuck(x) cout<<"* "<<x<<"\n"
using namespace std;
typedef long long LL;
const int N = 1e2 + 7;
const int INF = 0x3f3f3f3f;
struct lp {int x, y, num, step;
} AA, BB;
int n, m, ans;
char ar[N][N];
int dir[4][2] = {1,0,0,1,-1,0,0,-1};
int vis[N][N][8];
int sx, sy, ex, ey;
int kx[4], ky[4], cost[4];
inline int get_num(int x, int y) {for(int i = 1; i <= 3; ++i) if(x == kx[i] && y == ky[i]) return i;return -1;
}
inline int get_cost(int num) {int ans = 0;for(int i = 0; i < 3; ++i) if(num & (1 << i))ans = max(ans, cost[i + 1]);return ans;
}
void bfs() {for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) for(int k = 0; k <= 7; ++k)vis[i][j][k] = INF;queue<lp> Q;AA.x = sx, AA.y = sy, AA.num = 0;AA.step = 0;Q.push(AA);vis[sx][sy][0] = 0;while(!Q.empty()) {AA = Q.front(); Q.pop();if(AA.x == ex && AA.y == ey && AA.num == 7) {ans = min(AA.step, ans);continue;}int cc = get_cost(AA.num);//printf("x = %d y = %d step = %d num = %d\n\n", AA.x, AA.y, AA.step, AA.num);for(int i = 0; i < 4; ++i) {int px = AA.x + dir[i][0];int py = AA.y + dir[i][1];if(px <= 0 || py <= 0 || px > n || py > m) continue;if(ar[px][py] == '#' && AA.num == 7) continue;BB.step = AA.step + cc + 1;if(BB.step >= vis[px][py][AA.num]) continue;BB.x = px, BB.y = py;BB.num = AA.num;vis[px][py][BB.num] = BB.step;Q.push(BB);int key_num = get_num(px, py);if(key_num != -1 && ((BB.num&(1<<(key_num-1))) == 0)) {BB.num |= (1 << (key_num-1));if(BB.step >= vis[px][py][BB.num]) continue;vis[px][py][BB.num] = BB.step;Q.push(BB);}}}
}
int main() {
#ifndef ONLINE_JUDGEfreopen("E://A//shuju//5.in", "r", stdin);freopen("E://A//shuju//5.out", "w", stdout);  
#endifint tim;scanf("%d", &tim);while(tim --) {scanf("%d%d", &n, &m);for(int i = 1; i <= n; ++i) {scanf("%s", ar[i] + 1);for(int j = 1; j <= m; ++j) {if(ar[i][j] == 'S') sx = i, sy = j;if(ar[i][j] == 'E') ex = i, ey = j;if(ar[i][j] == 'X') kx[1] = i, ky[1] = j;if(ar[i][j] == 'Y') kx[2] = i, ky[2] = j;if(ar[i][j] == 'Z') kx[3] = i, ky[3] = j;}}for(int i = 1; i <= 3; ++i) scanf("%d", &cost[i]);ans = INF;bfs();printf("%d\n", ans);}return 0;
} 
 C++版本二
 題解:注意到題目說的當你沒有集齊所有快樂水的每次移動花費為1.所以你可以預處理出S,X,Y,Z四點之間的曼哈頓距離。然后終點以滿的花費跑一次有障礙物的普通bfs,記錄到X,Y,Z的最小體力花費。然后枚舉一遍X,Y,Z的收集順序,選取最優(yōu)解即可。此方法效率更高。
 
#include <bits/stdc++.h>
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int  T, n, m, sx, sy, lx, ly, ax, bx, cx, ay, by, cy, a, b, c;
char mp[105][105];
int dis[105][105];
bool vis[105][105];
int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
int p[5] = {1, 2, 3};
struct Node {int x, y, val;
} e[5];
struct node {int x, y, stp;node() {}node(int x, int y, int stp): x(x), y(y), stp(stp) {}
};
bool ok(int x, int y) {if (x < 1 || y < 1 || x > n || y > m) return 0;else return 1;
}
void bfs(int cost) {CLR(vis, 0);CLR(dis, 0x3f);dis[lx][ly] = 0;vis[lx][ly] = 1;queue<node> que;que.push(node(lx, ly, 0));while (!que.empty()) {node tmp = que.front(); que.pop();dis[tmp.x][tmp.y] = tmp.stp;for (int i = 0; i < 4; i++) {int dx = tmp.x + dir[i][0];int dy = tmp.y + dir[i][1];if (!ok(dx, dy)) continue;if (mp[dx][dy] == '#' || vis[dx][dy]) continue;vis[dx][dy] = 1;que.push(node(dx, dy, tmp.stp + cost));}}
}
int calc(int x1, int y1, int x2, int y2) {return abs(x1 - x2) + abs(y1 - y2);
}
int main() {scanf("%d", &T);while (T--) {scanf("%d%d", &n, &m);for (int i = 1; i <= n; i++) scanf("%s", mp[i] + 1);int tmp = 0;for (int i = 1, x; i <= 3; i++)  scanf("%d", &e[i].val), tmp = max(tmp, e[i].val);for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {if (mp[i][j] == 'S') {sx = i;sy = j;}else if (mp[i][j] == 'E') {lx = i;ly = j;}else if (mp[i][j] == 'X') {e[1].x = i;e[1].y = j;}else if (mp[i][j] == 'Y') {e[2].x = i;e[2].y = j;}else if (mp[i][j] == 'Z') {e[3].x = i;e[3].y = j;}}}bfs(tmp+1);int min_ans = INF;for(int i = 1; i <= 3; ++i) p[i] = i;do {/*for(int i = 1; i <= 3; ++i) printf("%d ", p[i]);printf("\n");*/int sum = dis[e[p[3]].x][e[p[3]].y];sum += calc(sx, sy, e[p[1]].x, e[p[1]].y);tmp = 0;for(int i = 1; i <= 2; ++i) {tmp = max(tmp, e[p[i]].val);sum += (tmp+1)*calc(e[p[i]].x, e[p[i]].y, e[p[i + 1]].x, e[p[i + 1]].y);}min_ans = min(min_ans, sum);} while (next_permutation(p + 1, p + 4));printf("%d\n", min_ans);}return 0;
} 
C++版本三?
 
#include "bits/stdc++.h"
using namespace std;
const int dir[4][2] = {-1,0,0,-1,0,1,1,0};
int N, M, sx, sy, ans, a[5];
bool che(int x, int y)
{return x>=1 && y>=1 && x<=N && y<=M;
}
char mp[105][105];
bool vis[105][105][10];
struct node
{int x ,y, state, speed, t;node(int a=0, int b=0, int c=0, int d=0, int tt=0):x(a), y(b), state(c), speed(d), t(tt) {}friend bool operator < (node e1, node e2) { return e1.t > e2.t; }
};
void bfs()
{memset(vis, false, sizeof(vis));priority_queue<node> Q;Q.push(node(sx,sy,0,0,0));vis[sx][sy][0] = true;while(!Q.empty()){node tmp = Q.top(); Q.pop();for(int i=0; i<4; i++){int xx = tmp.x + dir[i][0], yy = tmp.y + dir[i][1];if(!che(xx, yy) || (tmp.state == 7 && mp[xx][yy] == '#')) continue;if(mp[xx][yy] == 'E'){if(tmp.state == 7) { ans = tmp.t + tmp.speed + 1; return; }if(vis[xx][yy][tmp.state]) continue;vis[xx][yy][tmp.state] = true;Q.push(node(xx, yy, tmp.state, tmp.speed, tmp.t + tmp.speed + 1));}else if(mp[xx][yy]>='X' && mp[xx][yy]<='Z'){int id = (mp[xx][yy] - 'X');if( (tmp.state>>id) & 1){if(vis[xx][yy][tmp.state]) continue;vis[xx][yy][tmp.state] = true;Q.push(node(xx, yy, tmp.state, tmp.speed, tmp.t + tmp.speed + 1));}else{if(!vis[xx][yy][tmp.state]){vis[xx][yy][tmp.state] = true;Q.push(node(xx, yy, tmp.state, tmp.speed, tmp.t + tmp.speed + 1));}int state = (tmp.state | (1<<id)), speed = max(tmp.speed, a[id]);vis[xx][yy][state] = true;Q.push(node(xx, yy, state, speed, tmp.t + tmp.speed + 1));}}else{if(vis[xx][yy][tmp.state]) continue;vis[xx][yy][tmp.state] = true;Q.push(node(xx, yy, tmp.state, tmp.speed, tmp.t + tmp.speed + 1));}}}
}
int main()
{int T;  scanf("%d", &T);while(T--){scanf("%d%d", &N, &M);for(int i=1; i<=N; i++){scanf("%s", mp[i]+1);for(int j=1; j<=M; j++){if(mp[i][j] == 'S'){sx = i;sy = j;mp[i][j] = '.';}}}scanf("%d%d%d", &a[0], &a[1], &a[2]);//ans = INF;bfs();printf("%d\n", ans);}return 0;
} 
?
                            總結(jié)
                            
                                以上是生活随笔為你收集整理的huizhang要约会的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                            
                                如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。