思路:网络流分类里面的题目。。所以自然要想网络流啦。。。由题意可知:蜥蜴在高度>0的柱子上才有行动能力。。所以只要考虑高度大于0的柱子即可。.以图的每根柱子作为点,对于柱子u,如果u能到达的柱子v,就连接(u , v).如果是边有高度。。那么选定一个起点s连接所有蜥蜴的起点,权值设为1。所有能跳出边界的点连接终点t,权值设为inf。容量1代表这条边被经过一次。这样这个图能跳出去的蜥蜴数量就是从s->t的最大流。但是这个图是每个点有容量限制。这种我们可以把点拆成两个。拆点之后得到的两点,假如把u拆成两个(u1,u2),那么边(u1 , u2)的容量就是u的容量,然后把原来顶点指出的边变成出顶点指出,指向原来顶点的边变成从入顶点指入。这道题里面,先拆点,然后建图。注意两根不同柱子之间的容量要设为inf。然后跑一边dinic就好了。
代码:
#include<bits/stdc++.h> #define inf 0x3f3f3ff using namespace std; struct Node{int next , v , w;}e[500001]; int r , c ,d , cnt , tot,mp[30][30] ,mark[30][30], head[802] ,lv[802] , it[802]; void ins(int u , int v , int w) {e[tot].v = v , e[tot].w = w , e[tot].next = head[u] , head[u] = tot++;} void init() {tot=0,cnt = 0;memset(head,-1,sizeof(head));} void Insert(int u ,int v,int w) {ins(u,v,w);ins(v,u,0);} bool judge(int x1 , int y1,int x2 , int y2){ if(x1 <= 0 || y1 <= 0 || x2 <= 0 || y2 <= 0) return 0; if((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) <= d&&mp[x1][y1]&&mp[x2][y2]) return 1; return 0; } void build(){ for(int x1 = 1;x1 <= r;x1++) for(int y1 = 1; y1 <= c;y1++) for(int x2 = x1 - d;x2 <= x1 + d;x2++) for(int y2 = y1 - d;y2 <= y1 + d;y2++) if(judge(x1 , y1 , x2 , y2)) Insert(mark[x1][y1] + 400 , mark[x2][y2],inf); for(int x1 = 1; x1 <= r;x1++) for(int y1 = 1 ; y1 <= c;y1++) if(mp[x1][y1]) Insert(mark[x1][y1] ,mark[x1][y1] + 400 ,mp[x1][y1]); for(int x1 = 1; x1 <= r;x1++) for(int y1 = 1; y1 <= c;y1++) if(min(min(c-y1 + 1,y1) , min(x1 , r - x1 + 1))<= d) Insert(mark[x1][y1] + 400 , 801 , inf); } void bfs(int s){ memset(lv,-1,sizeof(lv)); queue<int>que; lv[s] = 0; que.push(s); while(!que.empty()){ int u = que.front(); que.pop(); for(int i = head[u];~i;i=e[i].next){ int v = e[i].v , w = e[i].w; if(w > 0 && lv[v] < 0) lv[v] = lv[u] + 1,que.push(v); } } } int dfs(int u ,int t , int f){ if(u==t) return f; int used = 0 , w; for(int i=head[u];~i;i=e[i].next){ int v = e[i].v; int w = e[i].w; if(lv[v] == lv[u]+1&&w > 0){ int d = dfs(v , t , min(f,w)); if(d > 0){ e[i].w -= f; e[i^1].w += f; return d; } } } return 0; } int max_flow(int s , int t){ int flow = 0; for(;;){ bfs(s); if(lv[t]<0) return flow; int f; while((f = dfs(s , t , inf))>0){ flow += f; } } return flow; } int main() { init(); scanf("%d%d%d",&r,&c,&d); char ch[30]; for(int i=1;i<=r;i++) for(int j = 1; j <= c;j++) mark[i][j] = ++cnt; int sum = 0; for(int i=1;i<=r;i++) { scanf("%s",ch+1); for(int j=1;j<=c;j++) mp[i][j] = ch[j] - '0'; } for(int i = 1; i <= r;i++) { scanf("%s",ch+1); for(int j = 1; j <= c;j++) if(ch[j] == 'L') { sum++; Insert(0 , mark[i][j] , 1); } } build(); printf("%d\n",sum - max_flow(0 , 801)); }