【BZOJ1294】[SCOI2009]围豆豆(动态规划,状压)

题面

BZOJ

洛谷

题解

首先考虑如何判断一个点是否在一个多边形内(不一定是凸的),我们从这个点开始,朝着一个方向画一条射线,看看它和这个多边形的变相交了几次,如果是奇数次那么一定在这个多边形内,否则不在。

这个可以感性理解一下,如果在内部的话,第一次碰到就是出了这个多边形,第二次又是进来,第三次又是出去......而最后总会出去,所以是奇数次。如果不在内部的话,显然就是进去出去是两两配对的,也就是偶数次。

那么我们可以在网格上从每一个豆豆开始向右侧画一条条的射线,那么和射线交的次数决定了这个豆豆是否在内。同时,放置射线和某条边界完全重合导致的不好计算,我们可以认为我们围豆豆的边在方格中线的偏上位置,而豆豆都恰好在格子的中心,这样子计算就要求强制跨越中线才算豆豆和这条线有交点,这样子就不会有问题了。

所以这个时候我们只需要钦定一个起点,设\(f[x][y][S]\)表示当前在点\((x,y)\),并且围住了\(S\)这些豆豆的最小边界长度,最后只需要在再回到起点就可以了。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
#define ll long long
#define MAX 15
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
char g[MAX][MAX];
int n,m,D,ans=-1e9,v[MAX];
int f[MAX][MAX][1<<9];
int sum[1<<9];
bool vis[MAX][MAX][1<<9];
struct Node{int x,y,S;};
int X[MAX],Y[MAX];
int d[4][2]={1,0,-1,0,0,1,0,-1};
int Get(int fx,int fy,int x,int y,int S)
{
for(int i=0;i<D;++i)
if(((fx==X[i]&&x>X[i])||(fx>X[i]&&x<=X[i]))&&y>Y[i])S^=1<<i;
return S;
}
void SPFA(int x,int y)
{
queue<Node> Q;memset(f,63,sizeof(f));
f[x][y][0]=0;Q.push((Node){x,y,0});
while(!Q.empty())
{
int x=Q.front().x,y=Q.front().y,S=Q.front().S;Q.pop();
for(int i=0;i<4;++i)
{
int xx=x+d[i][0],yy=y+d[i][1];
if(g[xx][yy]!='0')continue;
int SS=i<2?Get(x,y,xx,yy,S):S;
if(f[xx][yy][SS]>f[x][y][S]+1)
{
f[xx][yy][SS]=f[x][y][S]+1;
if(!vis[xx][yy][SS])vis[xx][yy][SS]=true,Q.push((Node){xx,yy,SS});
}
}
vis[x][y][S]=false;
}
for(int i=0;i<1<<D;++i)
ans=max(ans,sum[i]-f[x][y][i]);
}
int main()
{
n=read();m=read();D=read();
for(int i=0;i<D;++i)v[i]=read();
memset(g,'#',sizeof(g));
for(int i=1;i<=n;++i)scanf("%s",g[i]+1),g[i][m+1]='#';
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if(g[i][j]>='1'&&g[i][j]<='9')
X[g[i][j]-49]=i,Y[g[i][j]-49]=j;
for(int i=0;i<1<<D;++i)
for(int j=0;j<D;++j)
if(i&(1<<j))sum[i]+=v[j];
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if(g[i][j]=='0')
SPFA(i,j);
printf("%d\n",ans);
return 0;
}

【BZOJ1294】[SCOI2009]围豆豆(动态规划,状压)的更多相关文章

  1. 洛谷P2566 [SCOI2009]围豆豆(状压dp+spfa)

    题目传送门 题解 Σ(っ °Д °;)っ 前置知识 射线法:从一点向右(其实哪边都行)水平引一条射线,若射线与路径的交点为偶数,则点不被包含,若为奇数,则被包含.(但注意存在射线与路径重合的情况) 这 ...

  2. 洛谷P2566 [SCOI2009]围豆豆(状压dp+计算几何)

    题面 传送门 题解 首先要解决一个问题,就是怎么判断一个点是否在多边形内部 从这个点向某一个方向做一条射线,如果这条射线和多边形的交点为奇数说明在多边形内,否则在多边形外 然而有一些特殊情况,比方说一 ...

  3. [BZOJ1294][SCOI2009]围豆豆Bean 射线法+状压dp+spfa

    1294: [SCOI2009]围豆豆Bean Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 458  Solved: 305[Submit][Sta ...

  4. SCOI 2009 围豆豆(状压DP)

    SCOI 2009 围豆豆 题目描述 是不是平时在手机里玩吃豆豆游戏玩腻了呢?最近MOKIA手机上推出了一种新的围豆豆游戏,大家一起来试一试吧. 游戏的规则非常简单,在一个N×M的矩阵方格内分布着D颗 ...

  5. BZOJ1294: [SCOI2009]围豆豆Bean

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1294 状压dp,dis[s][i][j]表示从(i,j)出发围的状态是s的最短路. 然后判断一 ...

  6. bzoj1294 [SCOI2009]围豆豆

    Description Input 第一行两个整数N和M,为矩阵的边长. 第二行一个整数D,为豆子的总个数. 第三行包含D个整数V1到VD,分别为每颗豆子的分值. 接着N行有一个N×M的字符矩阵来描述 ...

  7. 【BZOJ1294】[SCOI2009]围豆豆Bean 射线法+状压DP+SPFA

    [BZOJ1294][SCOI2009]围豆豆Bean Description Input 第一行两个整数N和M,为矩阵的边长. 第二行一个整数D,为豆子的总个数. 第三行包含D个整数V1到VD,分别 ...

  8. 状态压缩动态规划 状压DP

    总述 状态压缩动态规划,就是我们俗称的状压DP,是利用计算机二进制的性质来描述状态的一种DP方式 很多棋盘问题都运用到了状压,同时,状压也很经常和BFS及DP连用,例题里会给出介绍 有了状态,DP就比 ...

  9. BZOJ 1294 [SCOI2009]围豆豆Bean ——计算几何

    显然我们不可能表示出一台路径,因为实在是太复杂了. 所以我们可以记录一下路径对答案的影响,显然路径对答案影响相同的时候,答案更优,所以我们可以用影响来代替路径. 所以我们考虑状压一下所有的豆子有没有被 ...

随机推荐

  1. odoo明细表汇总数据

    一.在主表中#改动地方 总结算金额 求和:def _get_subtotal2(self, cr, uid, ids, field_name, arg, context=None): # 初始化 re ...

  2. Linux内核RPC请求过程

    这篇文章讲讲server端RPC报文的处理流程.server端RPC报文的处理函数是svc_process,这个函数位于net/sunrpc/svc.c中.这个函数须要一个svc_rqst结构的指针作 ...

  3. WC 2019 游记 - 败者之低语

    败者之低语 WC 2019 游记 Day -1 看了一圈PKU和THU的题,感觉图像识别真有意思... 感觉非常讲道理,pku还是比thu简单一点的... 听说高二414在thu没有进面试? 震惊!( ...

  4. go语言之行--网络编程、http处理流程详情

    一.简介 go语言中的网络编程主要通过net包实现,net包提供了网络I/O接口,包括HTTP.TCP/IP.UDP.域名解析和Unix域socket等.和大多数语言一样go可以使用几行代码便可以启动 ...

  5. WPF之Manipulation

    原文:WPF之Manipulation 需求:现,在窗口下有一个StackPanel控件. 1.可以拖动. 2.可以展开及收缩(不仅仅可以拖动还可以点击) 3.窗口向坐标轴一样分四个象限,在不同的区域 ...

  6. 总是套路留人心, JAVA提供的套路: LinkedHashMap实现LRU缓存; InvocationHandler实现动态代理; fork/join实现窃取算法

    1. LinkedHashMap实现LRU缓存 LRU缓存核心是根据访问顺序排序, 自动移除队尾缓存, LinkedHashMap已经实现了这些要求: public LRUCache<K, V& ...

  7. 2_C语言中的数据类型 (九)数组

    1          数组 1.1       一维数组定义与使用 int array[10];//定义一个一维数组,名字叫array,一共有10个元素,每个元素都是int类型的 array[0] = ...

  8. maven常用命令集

    maven常用命令 mvn compile  编译主程序源代码,不会编译test目录的源代码.第一次运行时,会下载相关的依赖包,可能会比较费时间. mvn test-compile  编译测试代码,c ...

  9. Django实现websocket完成实时通讯、聊天室、在线客服等

    一 什么是Websocket WebSocket是一种在单个TCP连接上进行全双工通信的协议 WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据.在WebS ...

  10. N的阶乘:高精度

    N的阶乘 题目描述  输入一个正整数N,输出N的阶乘. 输入描述: 正整数N(0<=N<=1000) 输出描述:  输入可能包括多组数据,对于每一组输入数据,输出N的阶乘 示例1 输入 4 ...