题目:
题意:
在一张
n
∗
m
n*m
n∗m的图上有
d
d
d颗豆子,各有一个分数,我们可以选择任意点作为起点,向上下左右进行划范围,豆子和障碍是不允许被划在边界处,当划回起点的时候开始算分
此时的得分等于被划出来的封闭的多边形圈住的豆子的得分和
−
-
−划范围所用的步数
问最大得分是多少
分析:
豆子最多只能有
9
9
9颗,而每个豆子对于一种划法,直接点,就是有没有被圈住,那就可以往状压方面考虑了
动下手,我们对于每个豆子都向右作一条射线
(
f
r
o
m
@
h
z
o
i
l
i
u
c
h
a
n
g
)
:
(from\ @hzoi_liuchang ):
(from @hzoiliuchang):

不难发现,此时判定一个豆子是否被圈住,可以变成判断射线与划出的图形的交点的奇偶性
需要转换下思维,因为我们划范围的时候坐标表示的是图中的格点,但豆子却是占一个网格的,所以在判定的时候需要格外注意
设
f
x
,
y
,
s
f_{x,y,s}
fx,y,s表示当前划范围的最后停在的坐标位于
(
x
,
y
)
(x,y)
(x,y),此时被圈住的豆子的状态为
s
s
s时的步数
我们每次枚举一个起点,向四周不断拓展,当然记忆化是必不可少的
以
(
x
,
y
)
(x,y)
(x,y)为起点的答案,就是所有
s
s
s中的最大值
代码:
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define LL long long
using namespace std;
inline LL read()
{
LL s=0,f=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') {s=s*10+c-'0';c=getchar();}
return s*f;
}
int d[15],v[1000];
int t[15][15];
struct qwq{
int x,y,s;
};
int n,m,D;
int dis[15][15][1000],tf[15][15][1000];
int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
int ix[15],iy[15],ans=0;
void bfs(int xx,int yy)
{
queue<qwq> q;
q.push((qwq){xx,yy,0});
memset(tf,0,sizeof(tf));
memset(dis,0x3f,sizeof(dis));
dis[xx][yy][0]=0; tf[xx][yy][0]=1;
while(q.size())
{
int x=q.front().x,y=q.front().y,s=q.front().s,bc=s;
q.pop();
for(int i=0;i<4;i++)
{
int vx=x+dx[i],vy=y+dy[i];
if(vx<1||vy<1||vx>n||vy>m||t[vx][vy]) continue;
s=bc;
if(i==0||i==2)
for(int k=1;k<=D;k++)
if((x<ix[k]&&vx==ix[k]||x==ix[k]&&vx<ix[k])&&vy>iy[k])
s^=(1<<(k-1));
if(tf[vx][vy][s]) continue;
if(vx==1&&vy==1)
vx++,vx--;
tf[vx][vy][s]=1;
dis[vx][vy][s]=dis[x][y][bc]+1;
q.push((qwq){vx,vy,s});
}
}
for(int i=0;i<(1<<D);i++) ans=max(ans,v[i]-dis[xx][yy][i]);
return;
}
int main()
{
// freopen("data.in","r",stdin);
// freopen("1.out","w",stdout);
n=read();m=read();D=read();
for(int i=1;i<=D;i++) d[i]=read();
for(int i=0;i<(1<<D);i++)
for(int k=0;k<D ;k++)
v[i]+=d[k+1]*((i&(1<<k))?1:0);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
char c=getchar();
while((c<'0'||c>'9')&&c!='#') c=getchar();
if(c=='0') t[i][j]=0; else t[i][j]=1;
if(c>'0'&&c<='9') ix[c-'0']=i,iy[c-'0']=j;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(!t[i][j]) bfs(i,j);
cout<<ans;
return 0;
}

267

被折叠的 条评论
为什么被折叠?



