• [SCOI2007]蜥蜴


    题目背景

    07四川省选

    题目描述

    在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外。

    每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个石柱上。

    输入输出格式

    输入格式:

    输入第一行为三个整数r,c,d,即地图的规模与最大跳跃距离。以下r行为石柱的初始状态,0表示没有石柱,1~3表示石柱的初始高度。以下r行为蜥蜴位置,“L”表示蜥蜴,“.”表示没有蜥蜴。

    输出格式:

    输出仅一行,包含一个整数,即无法逃离的蜥蜴总数的最小值。

    输入输出样例

    输入样例#1:
    5 8 2
    00000000
    02000000
    00321100
    02000000
    00000000
    ........
    ........
    ..LLLL..
    ........
    ........
    
    输出样例#1:
    1

    说明

    100%的数据满足:1<=r, c<=20, 1<=d<=3

    题解:网络流

    把每个点的权值转移到边上,即拆点,在两个点之间连一条为这个点的权值的边

    把所有到这个点的入弧,连到原始点上,把出弧从拆的点发出,这就做到了把点的权值转移到边上

    对于每两个能互相跳到的石柱,连权值为INF的边

    建源点,汇点

    因为每个点只有一只蜥蜴,连一条从源点到这个点权值为1的边   //做的过程中连了权值为INF的边,调了好久。。。

    对于每个能令蜥蜴跳出地图的石柱,连一条从这个点到汇点权值为INF的边

    跑一遍dinic,蜥蜴个数减最大流即为答案

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    const int INF=1999999999;
    int r,c,d;int y=0;
    int mp1[21][21];bool mp2[21][21];int mp3[21][21];
    struct data{
    int next,to,cap;
    }g[200000];
    int iter[1000],h[1000],level[1000],k=1,head,tail,q[1000];
    void add(int from,int to,int cap)
    {
    g[++k].next=h[from];h[from]=k;g[k].to=to;g[k].cap=cap;
    g[++k].next=h[to];h[to]=k;g[k].to=from;g[k].cap=0;
    }
    void bfs(int s)
    {
    memset(level,0,sizeof(level));
    head=tail=0;q[tail++]=s;level[s]=1;
    while(head!=tail)
    {
    int u=q[head++];
    for(int i=h[u];i;i=g[i].next)
    {
    if(!level[g[i].to]&&g[i].cap)
    {
    level[g[i].to]=level[u]+1;q[tail++]=g[i].to;
    }
    }
    }
    }
    int dfs(int u,int t,int f)
    {
    if(u==t)return f;
    int used=0,w;
    for(int &i=iter[u];i;i=g[i].next)
    {
    if(g[i].cap&&level[g[i].to]==level[u]+1)
    {
    w=f-used;w=dfs(g[i].to,t,min(w,g[i].cap));
    if(w)
    {
    g[i].cap-=w;g[i^1].cap+=w;used+=w;if(used==f)return f;
    }
    }
    }
    return used;
    }
    int dinic(int s,int t)
    {
    int flow=0;
    for(;;)
    {
    for(int i=1;i<=2*y+2;i++)iter[i]=h[i];
    bfs(s);if(!level[t])return flow;
    flow+=dfs(s,t,INF);
    }
    }
    int main()
    {
    int gg=0;
    scanf("%d%d%d",&r,&c,&d);
    for(int i=1;i<=r;i++)
    {
    char cc[21];scanf("%s",cc);
    for(int j=1;j<=c;j++)mp1[i][j]=cc[j-1]-'0';
    }
    for(int i=1;i<=r;i++)
    {
    char cc[21];scanf("%s",cc);
    for(int j=1;j<=c;j++)
    {
    if(cc[j-1]=='L')mp2[i][j]=1,gg++;
    else mp2[i][j]=0;
    }
    }
    for(int i=1;i<=r;i++)
    for(int j=1;j<=c;j++)
    {
    if(mp1[i][j])mp3[i][j]=++y;
    }
    for(int i=1;i<=r;i++)
    for(int j=1;j<=c;j++)
    {
    for(int k1=1;k1<=r;k1++)
    for(int k2=1;k2<=c;k2++)
    {
    if(k1==i&&k2==j)continue;
    if((k1-i)*(k1-i)+(k2-j)*(k2-j)<=d*d&&mp1[i][j]&&mp1[k1][k2])
    {add(mp3[i][j]+y,mp3[k1][k2],INF);add(mp3[k1][k2]+y,mp3[i][j],INF);}
    }
    if(mp1[i][j])add(mp3[i][j],mp3[i][j]+y,mp1[i][j]);
    if(mp2[i][j])add(2*y+1,mp3[i][j],1);
    for(int k1=0;k1<=r+1;k1++)
    for(int k2=0;k2<=c+1;k2++)
    {
    if((k1==0||k1==r+1||k2==0||k2==c+1)&&(k1-i)*(k1-i)+(k2-j)*(k2-j)<=d*d&&mp1[i][j])
    {add(mp3[i][j]+y,2*y+2,INF);}
    }
    }
    cout<<gg-dinic(2*y+1,2*y+2);
    return 0;
    }
  • 相关阅读:
    基于学习的方法决定在哪些分支节点上运行heuristic算法
    深度学习结合树搜索求解集装箱预翻箱问题
    elementui el-tree 树节点颜色修改
    循环更新swingui并想动态看到效果,请使用invokeAndWait
    SwingWorker.publish 方法注释写的很清楚, 尤其是标红处
    GridBagConstraintsHelper 源码
    WeKeyWord微信关键字自动回复工具(一)初版
    WeFilesReciver微信文件接收助手(二)新增搜索
    模仿Cheat Engine内存搜索——(Sunday算法)
    WCarer微信客服工具(一)初版
  • 原文地址:https://www.cnblogs.com/lher/p/6550224.html
Copyright © 2020-2023  润新知