Weidoudou —————— State Compression DP

Wai Doudou

Input

The two integers N and M in the first row are the side lengths of the matrix. An integer D in the second line is the total number of beans. The third line contains D integers V1 to VD, which are the scores of each bean. Next, there is an N × M character matrix on the Nth row to describe the state of the game matrix, 0 means space and # means obstacle. The numbers 1 to 9 respectively indicate the corresponding number of beans.

Output

Contains only an integer, the highest possible score.

Sample Input

3 8
3
30 -100 30
00000000
010203#0
00000000

Sample Output

38

Hint

50% of the data satisfies \ (1≤D≤3 \) .
100% of the data satisfies \ (1≤D≤9, 1≤N, M≤10, -10000≤V_i≤10000 \) .

answer

Problem-solving ideas

This question seems quite hard, is quite hard
but to see the data range \ (1≤D≤9,1≤N, M≤10, -10000≤V_i≤10000 \
) quite small
considering violent state of compression DP
with A string of binary numbers represents the inclusion of each bean.
For example, \ (11010 \) means to include beans 2, 4, and 5.

There is also to determine whether a point is in the polygon.
Make any ray from this point. If the number of intersection points with the polygon is odd, it is inside the polygon, otherwise it is not

If this ray happens to cross the edge, then there is no way to find the number of intersections, so we only count the ones that have crossed this ray vertically (only for this question).
Look at the following example

0******0
0*0000*0
0*1****0
0***0000

Like this, 1 has passed 4 points to the right, but 1 actually
counts the points below this edge when it is counted in this polygon

Code

#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
const int N = 12;
int n, m, d, M, a[N], sum[1<<N], f[N][N][1<<N], v[N][N][1<<N], ans;
int dx[4] = {0, 0, 1, -1}, dy[4] = {1, -1, 0, 0}, fx[N], fy[N], cnt;
char c[N][N];
struct node {
    int x, y, s;
    node(int a, int b, int c) {
        x = a; y = b; s = c;
    }
};
queue<node> q;
void bfs(int x, int y) {
    memset(f, 0x3f, sizeof(f));
    memset(v, 0, sizeof(v));
    q.push(node(x, y, 0));
    f[x][y][0] = 0;
    while (!q.empty()) {
        node b = q.front(); q.pop();
        v[b.x][b.y][b.s] = 1;
        for(int i = 0; i < 4; i++) {
            int xx = b.x + dx[i], yy = b.y + dy[i], s = b.s;
            if (xx < 1 || yy < 1 || xx > n || yy > m || c[xx][yy] != '0') continue;
            if (i >= 2)
                for(int j = 1; j <= d; j++)
                    if (fx[j] == min(b.x, xx) && yy > fy[j])
                        s ^= 1 << (j - 1);
            if (!v[xx][yy][s] && f[xx][yy][s] > f[b.x][b.y][b.s]) {
                v[xx][yy][s] = 1;
                f[xx][yy][s] = f[b.x][b.y][b.s] + 1;
                q.push(node(xx, yy, s));
            }
        }
    } 
    for(int i = 0; i < M; i++)
        ans = max(ans, sum[i] - f[x][y][i]);
}
int main() {
    scanf("%d%d%d", &n, &m, &d);
    for(int i = 1; i <= d; i++)
        scanf("%d", &a[i]);
    M = 1 << d;
    for(int i = 0; i < M; i++)
        for(int j = 1; j <= d; j++)
            if (i & (1 << (j - 1)))
                sum[i] += a[j];
    for(int i = 1; i <= n; i++)
        scanf("%s", c[i]+1);
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            if (c[i][j] > '0' && c[i][j] <= '9')
                fx[c[i][j]-'0'] = i, fy[c[i][j]-'0'] = j;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            if (c[i][j] == '0') bfs(i, j);
    printf("%d", ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/Z8875/p/12714980.html