不能一一贪心暴搜,因为每个人的决策会对其他人产生影响
必须用能考虑到全局的做法
最大,全局,想到最大流
初始化dp[t][x][y][nx][ny] 表示在t时间内能从(x,y)到达(nx,ny)
有个地方要注意
假如某点在k+1时间之前已经infected,下一步不能取
但刚好在k+1时infected,可以到达
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
using namespace std;
#define INF 10000000
#define N 210
#define M 21000
struct Edge
{
int v,w;
}edge[M];
int adj[M],head[N],e;
void addedge(int u,int v,int w)
{
edge[e].v=v;edge[e].w=w;adj[e]=head[u];head[u]=e++;
edge[e].v=u;edge[e].w=0;adj[e]=head[v];head[v]=e++;
}
int S,T;
int dist[N],q[N*2],arc[N],gap[N],inq[N],pre[N];
int SAP(int s,int t)
{
memset(arc,-1,sizeof(arc));
memset(pre,-1,sizeof(pre));
int qf=0,qr=0;
q[qr++]=t;inq[t]=1;gap[0]++;dist[t]=0;
while(qf<qr)
{
int u=q[qf++];
for(int i=head[u];i!=-1;i=adj[i])
if(!inq[edge[i].v])
{
int v=edge[i].v;
q[qr++]=v;
inq[v]=1;
dist[v]=dist[u]+1;
gap[dist[v]]++;
arc[v]=head[v];
}
}
int low=INF,u=s,ans=0;
pre[s]=s;
while(dist[s]<t)
{
bool flag=false;
for(int &i=arc[u];i!=-1;i=adj[i])
if(edge[i].w && dist[edge[i].v]+1==dist[u])
{
flag=true;
low=min(low,edge[i].w);
pre[edge[i].v]=u;
u=edge[i].v;
if(u==t)
{
while(u!=s)
{
u=pre[u];
edge[arc[u]].w-=low;
edge[arc[u]^1].w+=low;
}
ans+=low;
low=INF;
}
break;
}
if(flag)
continue;
int mindis=t+1;
for(int i=head[u];i!=-1;i=adj[i])
if(edge[i].w && mindis>dist[edge[i].v])
{
mindis=dist[edge[i].v];
arc[u]=i;
}
gap[dist[u]]--;
if(gap[dist[u]]==0)
return ans;
dist[u]=mindis+1;
gap[dist[u]]++;
u=pre[u];
}
return ans;
}
char str[12][12],str2[12][12];
int sci[12][12],ca[12][12],stone[62][12][12];
int dp[62][12][12][12][12];
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int n,t;
void expand()
{
for(int k=1;k<=t;++k)
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
{
if(stone[k-1][i][j]==1)
stone[k][i][j]=1;
else if(stone[k-1][i][j]==2)
stone[k][i][j]=2;
else
{
int nx,ny;
for(int z=0;z<4;++z)
{
nx=i+dir[z][0];
ny=j+dir[z][1];
if(nx>=1&&nx<=n&&ny>=1&&ny<=n)
{
if(stone[k-1][nx][ny]==2)
stone[k][i][j]=2;
}
}
}
}
}
int vis[12][12];
void dfs(int x,int y,int nowx,int nowy,int k)
{
vis[nowx][nowy]=1;
dp[k][x][y][nowx][nowy]=1;
if(k>=t || stone[k][nowx][nowy])
return;
int nx,ny;
for(int z=0;z<4;++z)
{
nx=nowx+dir[z][0];
ny=nowy+dir[z][1];
if(nx>=1&&nx<=n&&ny>=1&&ny<=n && !vis[nx][ny])
{
if(stone[k][nx][ny])
continue;
dfs(x,y,nx,ny,k+1);
}
}
}
int main ()
{
scanf("%d%d",&n,&t);
for(int i=1;i<=n;++i)
{
scanf("%s",str[i]+1);
for(int j=1;j<=n;++j)
{
if(str[i][j]=='Z')
stone[0][i][j]=2;
else if(str[i][j]=='Y')
stone[0][i][j]=1;
else sci[i][j]=str[i][j]-'0';
}
}
for(int i=1;i<=n;++i)
{
scanf("%s",str2[i]+1);
for(int j=1;j<=n;++j)
{
if(str2[i][j]>='0' && str2[i][j]<='9')
ca[i][j]=str2[i][j]-'0';
}
}
expand();
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
if(sci[i][j])
{
memset(vis,0,sizeof(vis));
dfs(i,j,i,j,0);
}
for(int k=1;k<=t;++k)
for(int x=1;x<=n;++x)
for(int y=1;y<=n;++y)
for(int nx=1;nx<=n;++nx)
for(int ny=1;ny<=n;++ny)
{
dp[k][x][y][nx][ny]+=dp[k-1][x][y][nx][ny];
}
S=0;T=n*n*2+1;
memset(head,-1,sizeof(head));
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
addedge(S,(i-1)*n+j,sci[i][j]);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
addedge(n*n+(i-1)*n+j,T,ca[i][j]);
for(int x=1;x<=n;++x)
for(int y=1;y<=n;++y)
for(int nx=1;nx<=n;++nx)
for(int ny=1;ny<=n;++ny)
if(sci[x][y] && ca[nx][ny])
{
if(dp[t][x][y][nx][ny])
addedge((x-1)*n+y,n*n+(nx-1)*n+ny,INF);
}
int ans=SAP(S,T);
printf("%d\n",ans);
return 0;
}