POJ 3593 Sea Base Exploration, 状态压缩DP

地图中有K种物品, 

1.空载情况下每走一步用能量1

2.取得物品i需要能量Ai

3.每取得一个物品, 每走一步的能量需要加Bi

4.*为起点,图中不能经过*,取得K种物品后返回*

问能否用不大于P的能量取得K种物品

PS: 条件4,在求得起点到所有点的最短路径后,要将*看作#,然后重新计算每对点对的最短路径.


状态f[s][i][j] , s为二进制状态,最后取得第i种物品中编号为j的物品的最短路径.

f[s][i][j] = min(f[s - (1 << k)][i0][j0] + d[i][j][i0][j0] * (1 + C[s - (1 << k)]) + A[k]), 

其中(s >> k)&1 == 1, (s >> i0)&1 == 1, k != i0,

d[i][j][i0][j0]为第i种物品编号j到第i0种物品编号j0的距离,

C[s]记录状态s的每走一步需要的能量



  1 #include <iostream>
  2 #include <queue>
  3 #include <algorithm>
  4 using namespace std;
  5 
  6 #define INF  0x33333333
  7 #define min(a, b)   ((a) < (b) ? (a) : (b))
  8 char map[25][25];
  9 bool g[25][25];
 10 int id0[25][25], id1[25][25], id, A[10], B[10], C[1 << 10];
 11 int f[1 << 10][10][10], d[10][10][10][10], dd[10][10], cnt[10];
 12 int sta[1 << 10], one[1 << 10];
 13 int T, M, N, K, P, sx, sy, ans;
 14 int dir[4][2= {10-10010-1};
 15 
 16 int calt(int x)
 17 {
 18     int i = 0;
 19     while (x)
 20         x &= (x - 1), i++;
 21     return i;
 22 }
 23 
 24 int comp(int a, int b)
 25 {
 26     return one[a] < one[b];
 27 }
 28 
 29 void init()
 30 {
 31     for (int i = 0; i < (1 << K); i++)
 32     {
 33         sta[i] = i;
 34         C[i] = 0;
 35         for (int j = 0; j < K; j++)
 36             if ((i >> j)&1)
 37                 C[i] += B[j];
 38     }
 39     sort(sta, sta + (1 << K), comp);
 40 }
 41 
 42 void bfs(int y, int x, int ddd[][10], int id)
 43 {
 44     bool vis[25][25= {false};
 45     int tx, ty, dis;
 46     queue<int> Q;
 47     Q.push(y), Q.push(x), Q.push(0);
 48     vis[y][x] = true;
 49     while (!Q.empty())
 50     {
 51         y = Q.front(), Q.pop();
 52         x = Q.front(), Q.pop();
 53         dis = Q.front(), Q.pop();
 54         if (id0[y][x] != -1 && id0[y][x] != id)
 55             ddd[id0[y][x]][id1[y][x]] = dis;
 56         for (int i = 0; i < 4; i++)
 57         {
 58             tx = x + dir[i][0], ty = y + dir[i][1];
 59             if (!vis[ty][tx] && g[ty][tx])
 60             {
 61                 vis[ty][tx] = true;
 62                 Q.push(ty), Q.push(tx), Q.push(dis + 1);
 63             }
 64         }
 65     }
 66 }
 67 
 68 int main()
 69 {
 70     for (int i = 0; i < (1 << 10); i++)
 71         one[i] = calt(i);
 72     //freopen("test.in", "r", stdin);
 73     scanf("%d"&T);
 74     while (T--)
 75     {
 76         memset(map, '#'sizeof (map));
 77         memset(g, 0sizeof (g));
 78         memset(id0, -1sizeof (id0));
 79         memset(id1, -1sizeof (id1));
 80         memset(d, 0x33sizeof (d));
 81         memset(dd, 0x33sizeof (dd));
 82         memset(f, 0x33sizeof (f));
 83         memset(cnt, 0sizeof (cnt));
 84 
 85         scanf("%d %d %d %d"&M, &N, &K, &P);
 86         for (int i = 1; i <= M; i++)
 87             scanf("%s", map[i] + 1);
 88         for (int i = 0; i < K; i++)
 89             scanf("%d %d"&A[i], &B[i]);
 90 
 91         init();
 92         for (int i = 1; i <= M; i++)
 93             for (int j = 1; j <= N; j++)
 94                 if (map[i][j] != '#')
 95                 {
 96                     g[i][j] = true;
 97                     if (map[i][j] == '*')
 98                         sy = i, sx = j;
 99                     else if (map[i][j] != '.')
100                     {
101                         id0[i][j] = map[i][j] - 'A';
102                         id1[i][j] = cnt[map[i][j] - 'A']++;
103                     }
104                 }
105 
106         bfs(sy, sx, dd, -1);
107         g[sy][sx] = false;
108         for (int i = 1; i <= M; i++)
109             for (int j = 1; j <= N; j++)
110                 if (id0[i][j] != -1)
111                     bfs(i, j, d[id0[i][j]][id1[i][j]], id0[i][j]);
112 
113         for (int i = 1, i0, i1; i < (1 << K); i++)
114         {
115             i0 = sta[i];
116             for (int j = 0; j < K; j++)
117             {
118                 if ((i0 >> j)&1)
119                 {
120                     i1 = i0 - (1 << j);
121                     for (int c0 = 0; c0 < cnt[j]; c0++)
122                     {
123                         if (i1 > 0)
124                         {
125                             for (int k = 0; k < K; k++)
126                                 if ((i1 >> k)&1)
127                                     for (int c1 = 0; c1 < cnt[k]; c1++)
128                                         if (d[j][c0][k][c1] != INF && f[i1][k][c1] != INF)
129                                             f[i0][j][c0] = min(f[i0][j][c0], f[i1][k][c1] + d[j][c0][k][c1] *(1 + C[i1]) + A[j]);
130                         }
131                         else if (dd[j][c0] != INF)
132                             f[i0][j][c0] = min(f[i0][j][c0], dd[j][c0] + A[j]);
133                     }
134                 }
135             }
136         }
137         ans = INF;
138         for (int i = 0, k = (1 << K) - 1; i < K; i++)
139             for (int j = 0; j < cnt[i]; j++)
140                 if (f[k][i][j] + dd[i][j] * (1 + C[k]) <= P && dd[i][j] != INF && f[k][i][j] != INF)
141                     ans = min(ans, f[k][i][j] + dd[i][j] *(1 + C[k]));
142 
143         if (ans != INF)
144             printf("%d\n", ans);
145         else
146             printf("Impossible\n");
147     }
148     return 0;
149 

 


 


posted @ 2008-10-24 23:28  4h  阅读(644)  评论(0编辑  收藏  举报