题意:一张n*m的网格内每个点有话费,还有若干个宝藏,问一个人要走进去拿走所有宝藏在走出来的最小花费。
思路:看宝藏只有13个直接想到了状压dp[i][j]拿了哪几个前一个为j的最小花费,先bfs+优先队列预处理出最短路,然后记忆化搜索就可。
代码如下:
1 /************************************************** 2 * Author : xiaohao Z 3 * Blog : http://www.cnblogs.com/shu-xiaohao/ 4 * Last modified : 2014-05-15 16:59 5 * Filename : C.cpp 6 * Description : 7 * ************************************************/ 8 9 #include <iostream> 10 #include <cstdio> 11 #include <cstring> 12 #include <cstdlib> 13 #include <cmath> 14 #include <algorithm> 15 #include <queue> 16 #include <stack> 17 #include <vector> 18 #include <set> 19 #include <map> 20 #define MP(a, b) make_pair(a, b) 21 #define PB(a) push_back(a) 22 23 using namespace std; 24 typedef long long ll; 25 typedef pair<int, int> pii; 26 typedef pair<unsigned int,unsigned int> puu; 27 typedef pair<int, double> pid; 28 typedef pair<ll, int> pli; 29 typedef pair<int, ll> pil; 30 31 const int INF = 0x3f3f3f3f; 32 const double eps = 1E-6; 33 const int LEN = 210; 34 int Map[LEN][LEN], mp[LEN][LEN], out[LEN], in[LEN], dp[1<<13][20]; 35 int n, m, vn, N; 36 int xx[] = {0, 0, 1,-1}; 37 int yy[] = {1,-1, 0, 0}; 38 pii vex[LEN]; 39 40 bool J(int x, int y){ 41 if(x == 1 || x == n || y == 1 || y == m) return true; 42 return false; 43 } 44 45 bool Ja(int x, int y){ 46 if(x>0 && x<=n && y>0 && y<=m) return true; 47 return false; 48 } 49 50 struct P{ 51 int x, y, val; 52 bool operator<(const P a) const 53 { 54 return this->val > a.val; 55 } 56 }; 57 58 P mmp(int a, int b, int c){ 59 P ret; 60 ret.x = a;ret.y = b;ret.val = c; 61 return ret; 62 } 63 64 int Bfs(int sx, int sy, int ex, int ey){ 65 int vis[210][210] = {0}; 66 priority_queue<P> q; 67 q.push(mmp(sx, sy, 0)); 68 vis[sx][sy] = 1; 69 while(!q.empty()){ 70 P nv = q.top();q.pop(); 71 int x = nv.x, y = nv.y, val = nv.val; 72 if(ex < 0 && ey < 0){ 73 if(J(x, y)) return val; 74 } 75 else if(x == ex && y == ey) return val; 76 for(int i=0; i<4; i++){ 77 int tx = x + xx[i]; 78 int ty = y + yy[i]; 79 if(Ja(tx, ty) && !vis[tx][ty]){ 80 vis[tx][ty] = 1; 81 q.push(mmp(tx, ty, val + mp[tx][ty])); 82 } 83 } 84 } 85 return -1; 86 } 87 88 void init(){ 89 for(int i=0; i<vn; i++){ 90 for(int j=0; j<vn; j++){ 91 Map[i][j] = Bfs(vex[i].first, vex[i].second, vex[j].first, vex[j].second); 92 } 93 } 94 for(int i=0; i<vn; i++){ 95 int x = vex[i].first, y = vex[i].second; 96 out[i] = Bfs(x, y, -1, -1); 97 in[i] = out[i] + mp[x][y]; 98 } 99 } 100 101 int dfs(int x, int lv){ 102 if(dp[x][lv] != INF) return dp[x][lv]; 103 int cnt = 0; 104 for(int i=0; i<vn; i++){ 105 if(x & (1 << i)) cnt ++ ; 106 } 107 if(cnt == 1) return dp[x][lv] = in[lv]; 108 int ret = INF; 109 for(int i=0; i<vn; i++){ 110 if((x & (1<<i)) && i != lv){ 111 int &val = Map[i][lv]; 112 ret = min(ret, dfs(x^(1<<lv), i) + val); 113 } 114 } 115 return dp[x][lv] = ret; 116 } 117 118 int main() 119 { 120 // freopen("in.txt", "r", stdin); 121 122 int T, a, b; 123 scanf("%d", &T); 124 while(T--){ 125 scanf("%d%d", &n, &m); 126 memset(Map, 0x3f, sizeof Map); 127 memset(mp, 0, sizeof mp); 128 memset(dp, 0x3f, sizeof dp); 129 for(int i=1; i<=n; i++){ 130 for(int j=1; j<=m; j++){ 131 scanf("%d", &mp[i][j]); 132 if(mp[i][j] == -1) mp[i][j] = INF; 133 } 134 } 135 scanf("%d", &vn); 136 for(int i=0; i<vn; i++){ 137 scanf("%d%d", &a, &b); 138 a++, b++; 139 vex[i] = MP(a, b); 140 } 141 init(); 142 int ans = INF; 143 for(int i=0; i<vn; i++){ 144 ans = min(ans, dfs((1<<vn)-1, i) + out[i]); 145 } 146 if(ans != INF) printf("%d\n", ans); 147 else printf("0\n"); 148 } 149 return 0; 150 }
hdu 4568(状态压缩dp),布布扣,bubuko.com
原文:http://www.cnblogs.com/shu-xiaohao/p/3731308.html