zoukankan      html  css  js  c++  java
  • 【BZOJ】1294: [SCOI2009]围豆豆Bean

    题解

    随机跳题真好玩

    这个就是考虑我们怎么判断点在多边形内,就是点做一条射线,穿过了奇数条边

    我们只需要记录一个二进制状态表示每个点的射线穿过路径的次数的奇偶性

    枚举起点,然后用BFS的方式更新dp状态

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define mp make_pair
    #define pb push_back
    //#define ivorysi
    #define MAXN 300005
    using namespace std;
    typedef long long int64;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
        while(c < '0' || c > '9') {
        	if(c == '-') f = -1;
        	c = getchar();
        }
        while(c >= '0' && c <= '9') {
        	res = res * 10 + c - '0';
        	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) {
        	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    int N,M,D,val[MAXN],ql,qr;
    int dp[15][15][(1 << 9) + 5];
    int dx[4] = {0,1,0,-1},dy[4] = {1,0,-1,0};
    int tp[15][15][4],sum[(1 << 9) + 5];
    char s[15][15];
    struct node {
        int x,y,S;
    }que[1000005];
    int Calc(int x,int y) {
        int res = 0;
        for(int j = 1 ; j < y ; ++j) {
            if(s[x][j] >= '1' && s[x][j] <= '9') res |= (1 << (s[x][j] - '1'));
        }
        return res;
    }
    void Init() {
        read(N);read(M);read(D);
        for(int i = 1 ; i <= D ; ++i) read(val[i]);
        for(int i = 1 ; i <= N ; ++i) scanf("%s",s[i] + 1);
        for(int i = 1 ; i <= N ; ++i) {
            for(int j = 1 ; j <= M ; ++j) {
                if(s[i][j] == '0') {
                    for(int k = 0 ; k <= 3 ; ++k) {
                        int tx = i + dx[k],ty = j + dy[k];
                        if(tx >= 1 && tx <= N && ty >= 1 && ty <= M && s[tx][ty] == '0') {
                            if(tx != i) {
                                tp[i][j][k] = Calc(max(i,tx),j);
                            }
                        }
                        else tp[i][j][k] = -1;
                    }
                }
            }
        }
        for(int i = 0 ; i < (1 << D) ; ++i) {
            for(int j = 0 ; j < D ; ++j) {
                if(i >> j & 1) sum[i] += val[j + 1];
            }
        }
    }
    void BFS(int x,int y) {
        int ql = 1,qr = 0;
        que[++qr] = (node){x,y,0};
        dp[x][y][0] = 0;
        while(ql <= qr) {
            node u = que[ql++];
            for(int k = 0 ; k <= 3 ; ++k) {
                if(tp[u.x][u.y][k] != -1) {
                    if(dp[u.x + dx[k]][u.y + dy[k]][u.S ^ tp[u.x][u.y][k]] == -1) {
                        dp[u.x + dx[k]][u.y + dy[k]][u.S ^ tp[u.x][u.y][k]] = dp[u.x][u.y][u.S] + 1;
                        que[++qr] = (node){u.x + dx[k],u.y + dy[k],u.S ^ tp[u.x][u.y][k]};
                    }
                }
            }
        }
    }
    void Solve() {
        int ans = 0;
        for(int i = 1 ; i <= N ; ++i) {
            for(int j = 1 ; j <= M ; ++j) {
                if(s[i][j] != '0') continue;
                memset(dp,-1,sizeof(dp));
                BFS(i,j);
                for(int k = 0 ; k < (1 << D) ; ++k) {
                    if(dp[i][j][k] != -1) ans = max(ans,sum[k] - dp[i][j][k]);
                }
            }
        }
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Init();
        Solve();
        return 0;
    }
    
  • 相关阅读:
    MySQL/MariaDB 版本选择
    Linux查看某个进程的磁盘IO读写情况 pidstat
    Oracle 11gR2 Database UNDO表空间使用率居高不下处理
    Linux十字病毒查杀处理
    MySQL字符集与校对
    点与线、线与线之间的位置关系
    [向量] 点积应用-两个向量夹角
    点与线的距离及垂足点
    unity 4.6.1脚本解析出错,没有激活的勾,方法顺序出错
    Error building Player: Exception: Could not start java
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9878575.html
Copyright © 2011-2022 走看看