zoukankan      html  css  js  c++  java
  • S 围豆豆——————状态压缩DP

    围豆豆

    Input

    第一行两个整数N和M,为矩阵的边长。 第二行一个整数D,为豆子的总个数。 第三行包含D个整数V1到VD,分别为每颗豆子的分值。 接着N行有一个N×M的字符矩阵来描述游戏矩阵状态,0表示空格,#表示障碍物。而数字1到9分别表示对应编号的豆子。

    Output

    仅包含一个整数,为最高可能获得的分值。

    Sample Input

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

    Sample Output

    38
    

    Hint

    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
    用一串二进制数代表每个豆子的包含情况
    例如(11010)表示包含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;
    }
    
  • 相关阅读:
    内蒙古草原之行
    【iOS开发笔记25/50】:正则表达式
    读书笔记:《写给大家看的设计书》
    【iOS开发笔记22/50】:恼人的a valid provisioning profile for this executable was not found错误
    【搞定GTD】打造高效的OmniFocus系统
    【iOS开发笔记24/50】调整UIImage的大小
    【iOS开发笔记26/50】我自己写的苹果应用程序XQViewer终于上架了,解决了一系列的问题,终于挺过来了
    桥牌笔记:双挤
    养成一个习惯需要几年,而毁掉一下习惯只需要一天
    使用SuperMemo背单词2000天,抓图纪念一下!
  • 原文地址:https://www.cnblogs.com/Z8875/p/12714980.html
Copyright © 2011-2022 走看看