Description

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≤Vi≤10000。

正解:计算几何+状压$dp$+$spfa$。

这题的难点就在于如何判断一个豆子是否在多边形内。

实际上有一个很好判断的方法,那就是可以引一条水平线,看和多边形有几个交点,有奇数个交点就在多边形内,否则在多边形外。

但是还有一个情况。就是如果路径从上往下,突然往水平拐,再往下拐,那么这是有偶数个交点的,但是豆子还是在多边形内。

不过我们可以把所有边当成上开下闭的边,只有当水平线与一条边的下端点相交才算进去。

然后我们可以直接写一个状压+$spfa$。

 #include <bits/stdc++.h>
#define il inline
#define RG register
#define ll long long
#define inf (1<<29) using namespace std; struct data{ int x,y,bin; }p[]; const int d1[]={,,-,};
const int d2[]={-,,,}; int f[][][<<],vis[][][<<],g[][],val[],S,n,m,all,ans; queue<data> Q; il int gi(){
RG int x=,q=; RG char ch=getchar();
while ((ch<'' || ch>'') && ch!='-') ch=getchar();
if (ch=='-') q=-,ch=getchar();
while (ch>='' && ch<='') x=x*+ch-,ch=getchar();
return q*x;
} il char gc(){
RG char ch=getchar();
while ((ch<'' || ch>'') && ch!='#') ch=getchar();
return ch;
} il void spfa(RG int sx,RG int sy){
for (RG int i=;i<=n;++i)
for (RG int j=;j<=m;++j)
for (RG int k=;k<all;++k) f[i][j][k]=-inf;
Q.push((data){sx,sy,}),f[sx][sy][]=,vis[sx][sy][]=;
while (!Q.empty()){
RG data now=Q.front(); Q.pop();
if (now.x==sx && now.y==sy)
ans=max(ans,f[now.x][now.y][now.bin]);
for (RG int k=,x,y,yy,bin,del;k<;++k){
x=now.x+d1[k],y=now.y+d2[k];
if (x<= || x>n || y<= || y>m || g[x][y]) continue;
bin=now.bin,yy=max(y,now.y),del=;
if (k<=){
for (RG int i=;i<=S;++i)
if (p[i].y==yy && p[i].x<x){
bin^=<<(i-);
if (bin>>(i-)&) del+=val[i]; else del-=val[i];
}
}
if (f[x][y][bin]<f[now.x][now.y][now.bin]+del-){
f[x][y][bin]=f[now.x][now.y][now.bin]+del-;
if (!vis[x][y][bin]) vis[x][y][bin]=,Q.push((data){x,y,bin});
}
}
vis[now.x][now.y][now.bin]=;
}
return;
} int main(){
#ifndef ONLINE_JUDGE
freopen("bean.in","r",stdin);
freopen("bean.out","w",stdout);
#endif
n=gi(),m=gi(),S=gi(),all=<<S;
for (RG int i=;i<=S;++i) val[i]=gi();
for (RG int i=;i<=n;++i)
for (RG int j=;j<=m;++j){
RG char ch=gc();
if (ch=='#') g[i][j]=-; else g[i][j]=ch-'';
if (g[i][j]>= && g[i][j]<=) p[g[i][j]]=(data){i,j};
}
for (RG int i=;i<=n;++i)
for (RG int j=;j<=m;++j) if (!g[i][j]) spfa(i,j);
cout<<ans; return ;
}

bzoj1294 [SCOI2009]围豆豆的更多相关文章

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

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

  2. BZOJ1294: [SCOI2009]围豆豆Bean

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

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

    [BZOJ1294][SCOI2009]围豆豆(动态规划,状压) 题面 BZOJ 洛谷 题解 首先考虑如何判断一个点是否在一个多边形内(不一定是凸的),我们从这个点开始,朝着一个方向画一条射线,看看它 ...

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

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

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

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

  6. [SCOI2009]围豆豆

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

  7. 【题解】SCOI2009围豆豆

    很久之前就很想做的一道题,一直思考到今天才下定决心看题解.这道题中,很关键的一点就在于:如何判断一个点是否在一个多边形内?其实如果计算几何基本功扎实的话,应该是可以很快给出答案的(可惜我完全不行):由 ...

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

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

  9. 【状态压缩DP】SCOI2009 围豆豆

    题目大意 洛谷链接 在一个\(N×M\)的矩阵方格内分布着\(D\)颗豆子,每颗豆有不同的分值\(V_i\).游戏者可以选择任意一个方格作为起始格,每次移动可以随意的走到相邻的四个格子,直到最终又回到 ...

随机推荐

  1. Oracle EBS AP更新供应商地址

    SELECT pvs.vendor_site_id, pvs.party_site_id, hps.party_site_name, hps.object_version_number, hps.pa ...

  2. 排序算法(2) 堆排序 C++实现

    堆 1 数组对象 2 可以视为一棵完全二叉树 3 一个堆可以被看作一棵二叉树和一个数组,如下图所示: 4 下标计算(通常使用内联函数或者宏来定义下标操作): 已知某个结点的下标为i 其父节点下标:i/ ...

  3. memset struct含有string的崩溃

    2019/4/2 补充一下 这里如果填充为0,则不会崩溃,填充为非0时,再次调用赋值就会崩溃 推测非0拷贝破坏了string内部的数据结构,不要对任何类使用memset https://blog.cs ...

  4. JavaScript计算指定日期与当前日期的相差天数

    java中处理2个时间段相差几天很容易,直接调相关方法就行,不过js处理这类问题稍微有点不易,项目开发中也用到了,如下: 1 2 3 4 5 6 7 8 9 10 11 12 //计算两个日期天数差的 ...

  5. MySQL-5.6版本GTID的主从复制

    mysql GTID Replication 一.GTID的概述: 1.全局事物标识:global transaction identifieds. 2.GTID事物是全局唯一性的,且一个事务对应一个 ...

  6. 【[TJOI2015]弦论】

    \(SA+SAM\) 第一问显然是一个\(SAM\)的经典问题,我们排完序之后直接使用一直往下找\(n+1-sa[i]-het[i]\)就好了,找到\(K\)减不动了输出就好了 第二问是\(SAM\) ...

  7. 【openjudge】【前缀和】P6731啤酒厂选址

    [描述] 海上有一个岛,在环海边上建有一条环岛高速公路,沿着公路有n(5 < n < 10000)个居民点,假设每个居民点有一个编号,从0开始,按顺时针依次从小到大(即,0,1,…,n-1 ...

  8. Linux 无法连接网络排查方法

    .hosts文件增加 127.0.0.1 对localhost的解析. .检查/etc/resove.cnf dns配置是否正确 .route命令检查是否有默认路由,没有就 route add 网段 ...

  9. Lambda表达式学习(1)

    项目里面需要经常对一系列同类型集合进行操作 ,  如对集合进行增加元素 ,  删除集合的指定索引的元素等等.我们可以使用ArrayList来进行. 如 ArrayList stringArrayLis ...

  10. 命令行编译执行java

    命令行编译运行java程序 使用命令 javac进行编译 和 java进行执行. javac 后面跟着的是java文件的文件名,例如 HelloWorld.java. 该命令用于将 java 源文件编 ...