Weidoudou ——————国家圧縮DP

ワイドウ

入力

最初の行の2つの整数NとMは、行列の辺の長さです。2行目の整数Dは、Beanの総数です。3行目には、各BeanのスコアであるD整数V1からVDが含まれています。次に、ゲーム行列の状態を説明するためにN行目にN×Mの文字行列があり、0はスペースを表し、#は障害物を表します。1から9までの数字は、対応する豆の数をそれぞれ示しています。

出力

整数のみを含みます。最高スコアです。

入力例

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

出力例

38

ヒント

データの50%が\(1≤D≤3\)を満たします。
データの100%は\(1≤D≤9、1≤N、M≤10、-10000≤V_i≤10000\)を満たします。

解決策

問題解決のアイデア

この質問は、かなり難しいようで、非常に難しいです
が、データの範囲を参照してください(1≤D≤9,1≤N、M≤10、-10000≤V_i≤10000\ \ )
は非常に小さい
考慮暴力的な圧縮DPの状態を
と2進数の文字列は、各Beanの包含を表します。
たとえば、\(11010 \)は、Bean 2、4、および5を含めることを意味します。

また、ポイントがポリゴン内にあるかどうかを判別することも
できます。このポイントからレイを作成します。ポリゴンとの交点の数が奇数の場合は、ポリゴン内にあり、そうでない場合はそうではありません。

この光線がエッジを横切った場合、交差の数を見つける方法がないため、この光線を垂直に横切ったものだけをカウントします(この質問のみ)。
次の例を見てください

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

このように、1は右に4ポイントを通過
しましたが、このポリゴンでカウントされるとき、1は実際にはこのエッジの下のポイントをカウントします

コード

#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;
}

おすすめ

転載: www.cnblogs.com/Z8875/p/12714980.html