zoukankan      html  css  js  c++  java
  • [BZOJ1294][SCOI2009]围豆豆Bean

    [BZOJ1294][SCOI2009]围豆豆Bean

    试题描述

    OwO

    输入

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

    输出

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

    输入示例

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

    输出示例

    38
    

    数据规模及约定

    (50 exttt{%}) 的数据满足 (1 le D le 3)

    (100 exttt{%}) 的数据满足 (1 le D le 9)(1 le N, M le 10)(-10000 le V_i le 10000)

    题解

    传说中的射线法。判断一个点是否在一个任意多边形内部可以从这个点向任意一个方向引一条射线,若多边形的边交它奇数次则该点在多边形内,否则不在。

    这道题对于每个豆豆我们向右水平引一条射线,然后状压,在经过射线的时候改变一些豆子是否在内部的状态,枚举起点 BFS 即可。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    #define rep(i, s, t) for(int i = (s); i <= (t); i++)
    #define dwn(i, s, t) for(int i = (s); i >= (t); i--)
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 15
    #define maxs 512
    
    int n, m, D, val[maxn], beans[maxn][maxn], sum[maxs];
    char Map[maxn][maxn];
    struct Node {
    	int x, y, S; bool ud, from;
    	Node() {}
    	Node(int _1, int _2, int _3, bool _4, bool _5): x(_1), y(_2), S(_3), ud(_4), from(_5) {}
    } Q[maxn*maxn*maxs<<2];
    int step[maxn][maxn][maxs][2][2], ans, dx[4] = {-1, 1, 0, 0}, dy[4] = {0, 0, -1, 1};
    bool iszero(int x, int y) { return 1 <= x && x <= n && 1 <= y && y <= m && Map[x][y] == '0'; }
    void solve(int sx, int sy) {
    	memset(step, -1, sizeof(step));
    	int hd = 0, tl = 0;
    	if(beans[sx][sy]) {
    		if(sx > 1) step[sx][sy][0][0][0] = 0, Q[++tl] = Node(sx, sy, 0, 0, 0);
    		if(sx < n) step[sx][sy][0][1][1] = 0, Q[++tl] = Node(sx, sy, 0, 1, 1);
    	}
    	else step[sx][sy][0][0][0] = 0, Q[++tl] = Node(sx, sy, 0, 0, 0);
    	while(hd < tl) {
    		Node u = Q[++hd];
    		rep(i, 0, 3) {
    			Node v(u.x + dx[i], u.y + dy[i], u.S, u.ud, u.from);
    			if(iszero(v.x, v.y)) {
    				if(dx[i]) {
    					if(beans[u.x][u.y] && ((dx[i] == -1 && u.ud) || (dx[i] == 1 && !u.ud)))
    						v.S ^= beans[u.x][u.y];
    					if(beans[v.x][v.y]) v.ud = dx[i] == -1;
    					else v.ud = 0;
    				}
    				if(step[v.x][v.y][v.S][v.ud][v.from] >= 0) continue;
    				step[v.x][v.y][v.S][v.ud][v.from] = step[u.x][u.y][u.S][u.ud][u.from] + 1;
    				Q[++tl] = v;
    			}
    		}
    	}
    	rep(S, 0, (1 << D) - 1) {
    		if(beans[sx][sy]) {
    			if(step[sx][sy][0][0][0] >= 0) {
    				if(step[sx-1][sy][S][0][0] >= 0) ans = max(ans, sum[S^beans[sx-1][sy]] - step[sx-1][sy][S][0][0] - 1);
    				if(step[sx-1][sy][S][1][0] >= 0) ans = max(ans, sum[S] - step[sx-1][sy][S][1][0] - 1);
    			}
    			if(step[sx][sy][0][1][1] >= 0) {
    				if(step[sx+1][sy][S][0][1] >= 0) ans = max(ans, sum[S] - step[sx+1][sy][S][0][1] - 1);
    				if(step[sx+1][sy][S][1][1] >= 0) ans = max(ans, sum[S^beans[sx+1][sy]] - step[sx+1][sy][S][1][1] - 1);
    			}
    		}
    		else {
    			if(step[sx][sy][S][0][0] >= 0) ans = max(ans, sum[S] - step[sx][sy][S][0][0]);
    			if(step[sx][sy][S][1][0] >= 0) ans = max(ans, sum[S] - step[sx][sy][S][1][0]);
    		}
    	}
    	return ;
    }
    
    int main() {
    	n = read(); m = read(); D = read();
    	rep(i, 1, D) val[i] = read();
    	rep(i, 1, n) scanf("%s", Map[i] + 1);
    	
    	rep(i, 1, n) rep(j, 1, m)
    		if('1' <= Map[i][j] && Map[i][j] <= '9')
    			rep(k, j, m) beans[i][k] |= (1 << Map[i][j] - '1');
    	
    	rep(S, 0, (1 << D) - 1)
    		rep(j, 0, D - 1) if(S >> j & 1) sum[S] += val[j+1];
    	rep(i, 1, n) rep(j, 1, m) if(Map[i][j] == '0') solve(i, j);
    	
    	printf("%d
    ", ans);
    	
    	return 0;
    }
    

    一个小技巧:每个豆子可以看成是它所在的方格的上边界的中点,从这个中点向右引射线,这样会好做很多。(想一想,为什么这样是对的)

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    #define rep(i, s, t) for(int i = (s); i <= (t); i++)
    #define dwn(i, s, t) for(int i = (s); i >= (t); i--)
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 15
    #define maxs 512
    
    int n, m, D, val[maxn], beans[maxn][maxn];
    char Map[maxn][maxn];
    
    struct Node {
    	int x, y, S;
    	Node() {}
    	Node(int _1, int _2, int _3): x(_1), y(_2), S(_3) {}
    } Q[maxn*maxn*maxs];
    int step[maxn][maxn][maxs], ans, dx[4] = {-1, 1, 0, 0}, dy[4] = {0, 0, -1, 1};
    bool iszero(int x, int y) { return 1 <= x && x <= n && 1 <= y && y <= m && Map[x][y] == '0'; }
    void solve(int sx, int sy) {
    	memset(step, -1, sizeof(step));
    	step[sx][sy][0] = 0;
    	int hd = 0, tl = 0;
    	Q[++tl] = Node(sx, sy, 0);
    	while(hd < tl) {
    		Node u = Q[++hd];
    		rep(i, 0, 3) {
    			Node v(u.x + dx[i], u.y + dy[i], u.S);
    			if(iszero(v.x, v.y)) {
    				if(beans[v.x][v.y] && dx[i] == 1) v.S ^= beans[v.x][v.y];
    				if(beans[u.x][u.y] && dx[i] == -1) v.S ^= beans[u.x][u.y];
    				if(step[v.x][v.y][v.S] >= 0) continue;
    				step[v.x][v.y][v.S] = step[u.x][u.y][u.S] + 1;
    				Q[++tl] = v;
    			}
    		}
    	}
    	rep(S, 0, (1 << D) - 1) {
    		int sum = 0;
    		rep(i, 0, D - 1) if(S >> i & 1) sum += val[i+1];
    		if(step[sx][sy][S] >= 0) ans = max(ans, sum - step[sx][sy][S]);
    	}
    	return ;
    }
    
    int main() {
    	n = read(); m = read(); D = read();
    	rep(i, 1, D) val[i] = read();
    	rep(i, 1, n) scanf("%s", Map[i] + 1);
    	
    	rep(i, 1, n) rep(j, 1, m)
    		if('1' <= Map[i][j] && Map[i][j] <= '9')
    			rep(k, j, m) beans[i][k] |= (1 << Map[i][j] - '1');
    	rep(i, 1, n) rep(j, 1, m) if(Map[i][j] == '0') solve(i, j);
    	
    	printf("%d
    ", ans);
    	
    	return 0;
    }
    
  • 相关阅读:
    Spring DI模式 小样例
    java中经常使用的日期格式化(全)
    循环-15. 统计素数并求和(20)
    [Unity3D]Unity3D游戏开发之自己主动寻路与Mecanim动画系统的结合
    【UVA】11732
    Mac OS使用技巧之十六:系统失去响应怎么办?
    C# 保存窗口为图片(保存纵断面图)
    Linux Resin 安装
    Etcd学习(二)集群搭建Clustering
    android中选择控件与选择界面自然过度效果的实现--一种新的交互设计
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/7718520.html
Copyright © 2011-2022 走看看