【BZOJ1294】[SCOI2009]围豆豆(动态规划,状压)
【BZOJ1294】[SCOI2009]围豆豆(动态规划,状压)
题面
题解
首先考虑如何判断一个点是否在一个多边形内(不一定是凸的),我们从这个点开始,朝着一个方向画一条射线,看看它和这个多边形的变相交了几次,如果是奇数次那么一定在这个多边形内,否则不在。
这个可以感性理解一下,如果在内部的话,第一次碰到就是出了这个多边形,第二次又是进来,第三次又是出去......而最后总会出去,所以是奇数次。如果不在内部的话,显然就是进去出去是两两配对的,也就是偶数次。
那么我们可以在网格上从每一个豆豆开始向右侧画一条条的射线,那么和射线交的次数决定了这个豆豆是否在内。同时,放置射线和某条边界完全重合导致的不好计算,我们可以认为我们围豆豆的边在方格中线的偏上位置,而豆豆都恰好在格子的中心,这样子计算就要求强制跨越中线才算豆豆和这条线有交点,这样子就不会有问题了。
所以这个时候我们只需要钦定一个起点,设\(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]围豆豆(动态规划,状压)的更多相关文章
- 洛谷P2566 [SCOI2009]围豆豆(状压dp+spfa)
		
题目传送门 题解 Σ(っ °Д °;)っ 前置知识 射线法:从一点向右(其实哪边都行)水平引一条射线,若射线与路径的交点为偶数,则点不被包含,若为奇数,则被包含.(但注意存在射线与路径重合的情况) 这 ...
 - 洛谷P2566 [SCOI2009]围豆豆(状压dp+计算几何)
		
题面 传送门 题解 首先要解决一个问题,就是怎么判断一个点是否在多边形内部 从这个点向某一个方向做一条射线,如果这条射线和多边形的交点为奇数说明在多边形内,否则在多边形外 然而有一些特殊情况,比方说一 ...
 - [BZOJ1294][SCOI2009]围豆豆Bean  射线法+状压dp+spfa
		
1294: [SCOI2009]围豆豆Bean Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 458 Solved: 305[Submit][Sta ...
 - SCOI 2009 围豆豆(状压DP)
		
SCOI 2009 围豆豆 题目描述 是不是平时在手机里玩吃豆豆游戏玩腻了呢?最近MOKIA手机上推出了一种新的围豆豆游戏,大家一起来试一试吧. 游戏的规则非常简单,在一个N×M的矩阵方格内分布着D颗 ...
 - BZOJ1294: [SCOI2009]围豆豆Bean
		
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1294 状压dp,dis[s][i][j]表示从(i,j)出发围的状态是s的最短路. 然后判断一 ...
 - bzoj1294 [SCOI2009]围豆豆
		
Description Input 第一行两个整数N和M,为矩阵的边长. 第二行一个整数D,为豆子的总个数. 第三行包含D个整数V1到VD,分别为每颗豆子的分值. 接着N行有一个N×M的字符矩阵来描述 ...
 - 【BZOJ1294】[SCOI2009]围豆豆Bean 射线法+状压DP+SPFA
		
[BZOJ1294][SCOI2009]围豆豆Bean Description Input 第一行两个整数N和M,为矩阵的边长. 第二行一个整数D,为豆子的总个数. 第三行包含D个整数V1到VD,分别 ...
 - 状态压缩动态规划  状压DP
		
总述 状态压缩动态规划,就是我们俗称的状压DP,是利用计算机二进制的性质来描述状态的一种DP方式 很多棋盘问题都运用到了状压,同时,状压也很经常和BFS及DP连用,例题里会给出介绍 有了状态,DP就比 ...
 - BZOJ 1294 [SCOI2009]围豆豆Bean ——计算几何
		
显然我们不可能表示出一台路径,因为实在是太复杂了. 所以我们可以记录一下路径对答案的影响,显然路径对答案影响相同的时候,答案更优,所以我们可以用影响来代替路径. 所以我们考虑状压一下所有的豆子有没有被 ...
 
随机推荐
- 【实战】verilog中`define的使用记录
			
背景: 在最近实战开发中发现:对外部芯片进行初始化时,往往需要定义大量参数. 若直接在module中通过localparam或者parameter进行参数定义的话,会带来两个问题: 1.代码长度增加, ...
 - [Oracle]OpenVMS 运行 Oracle 时的推荐值
			
PQL Parameters ORACLE Account ------------------ ------------------------- PQL_M ...
 - SQLServer数据库还原:无法在已有的mdf文件上还原文件
			
如果提示无法在已有的mdf文件上还原文件,请修改如下位置
 - PowerBI开发 第二篇:数据建模
			
在分析数据时,不可能总是对单个数据表进行分析,有时需要把多个数据表导入到PowerBI中,通过多个表中的数据及其关系来执行一些复杂的数据分析任务,因此,为准确计算分析的结果,需要在数据建模中,创建数据 ...
 - Solr 后台查询实例 (工作备查)
			
有时间再进行整理package xxx.service.impl; import java.util.HashMap; import java.util.Map; import java.util.M ...
 - 并发编程(Concurrent programming)
			
并发编程(Concurrent programming) 1.并发编程概述 2.委托(delegate) 3.事件(event) 4.线程(thread) 5.线程池(threadPool) 6.任务 ...
 - Dubbo+zookeeper搭建环境学习笔记
			
Dubbo背景和简介 Dubbo开始于电商系统,因此在这里先从电商系统的演变讲起. 1.单一应用框架(ORM) 当网站流量很小时,只需一个应用,将所有功能如下单支付等都部署在一起,以减少部署节点和成本 ...
 - NodeJS旅程 : Less
			
我一直强调我是个很懒的人,虽然我认为自己是个代码控但不代表我喜欢写大量代码.有做Web前端开发的人一定都接触CSS,由其在当下CSS3更是做出Cool站的必修课.我曾和不少的前端开发讨论过CSS3,我 ...
 - 2014.8.23 Research Meeting Report
			
Dear All: It was good talk yesterday. However, I want to emphasize that, finally it is the *work* an ...
 - PBFT_拜占庭容错算法
			
根据论文<Practical Byzantine Fault Tolerance and Proactive Recovery>整理 Practical byzantine fault t ...