bzoj1066

1066: [SCOI2007]蜥蜴

Time Limit: 1 Sec   Memory Limit: 162 MB
Submit: 1963   Solved: 950
[ Submit][ Status]

Description

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

Input

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

Output

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

Sample Input

5 8 2
00000000
02000000
00321100
02000000
00000000
........
........
..LLLL..
........
........

Sample Output

1

HINT

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


终于开刷网络流的题目,建模真是一大难点啊。此题竟然可以用网络流建模...

仔细想想还是有道理的,因为每根柱子最多跳出h(高度)个蜥蜴,这不正是网络流中的流量限制条件吗?

将每根柱子假想成一根管道,蜥蜴从一端跳入,另一端跳出。

将超级源点对每个蜥蜴所在柱子连一条边权为1的边,限制蜥蜴的流入。

将所有有高度的并且可能使蜥蜴跳出边界的柱子连向超级源点,权值为无穷大,这代表蜥蜴可以越界的个数。

将所有有高度的柱子彼此(距离小于等于d)尾部连首部,表示蜥蜴可以跳来跳去,恰好一只蜥蜴跳一下,模型中一根柱子的流量会减1,通过另一根柱子往汇点方向传递。

这真是太完美的网络流模型了!可是初学很难想到。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#define Maxn 1610
using namespace std;

const int inf=0x3f3f3f3f;
struct line{
    int to,next,cap;
}p[640010];
struct point{
    int x,y,w;
    point(int xx,int yy,int ww):x(xx),y(yy),w(ww){}
};
vector<point> dv;
int head[Maxn]; //初始化-1
int q[Maxn]; //BFS队列
int d[Maxn]; //层次
int tot; //初始化0
int src,t; //源点,汇点
char s[30][30];
int vis[30][30];
void addedge(int a,int b,int c){
    p[tot].to=b;
    p[tot].next=head[a];
    p[tot].cap=c;
    head[a]=tot++;
}
void insert(int a,int b,int c){
    addedge(a,b,c);
    addedge(b,a,0);
}
bool bfs(){
    memset(d,-1,sizeof d);
    int s=0,e=-1;
    q[++e]=src;
    d[src]=0;
    while(s<=e){
        int u=q[s++];
        for(int i=head[u];i!=-1;i=p[i].next){
            int v=p[i].to;
            if(d[v]==-1&&p[i].cap){
                d[v]=d[u]+1;
                q[++e]=v;
            }
        }
    }
    return d[t]!=-1;
}
int dfs(int u,int alpha){
    if(u==t) return alpha;
    int w,used=0;
    for(int i=head[u];i!=-1&&used<alpha;i=p[i].next){
        int v=p[i].to;
        if(p[i].cap&&d[v]==d[u]+1){
            w=dfs(v,min(alpha-used,p[i].cap));
            used+=w;
            p[i].cap-=w;
            p[i^1].cap+=w;
        }
    }
    if(!used) d[u]=-1;
    return used;
}
int dinic(){
    int ans=0;
    src=0,t=1000;
    while(bfs())
        ans+=dfs(src,inf);
    return ans;
}
bool dis(int i,int j,int d){
    return (dv[i].x-dv[j].x)*(dv[i].x-dv[j].x)+
    (dv[i].y-dv[j].y)*(dv[i].y-dv[j].y)<=d*d;
}
int main()
{
    int r,c,d;
    cin>>r>>c>>d;
    memset(head,-1,sizeof head);
    tot=0;
    for(int i=0;i<r;i++){
        scanf("%s",s[i]);
        for(int j=0;s[i][j];j++)
            if(s[i][j]!='0')
                dv.push_back(point(i,j,s[i][j]-'0'));
    }
    int cnt=0;
    memset(vis,0,sizeof vis);
    for(int i=0;i<r;i++){
        scanf("%s",s[i]);
        for(int j=0;s[i][j];j++)
            if(s[i][j]=='L'){
                vis[i][j]=1;
                cnt++;
            }
    }
    for(int i=0;i<dv.size();i++){
        if(vis[dv[i].x][dv[i].y])
            insert(0,i+1,1); //超级源
        insert(i+1,i+501,dv[i].w); //柱子拆分
    }
    for(int i=0;i<dv.size();i++)
        for(int j=0;j<dv.size();j++)
            if(i!=j&&dis(i,j,d))
                insert(i+501,j+1,inf); //柱子间
    for(int i=0;i<dv.size();i++)
        if(dv[i].x-d<0||dv[i].x+d>=r||dv[i].y-d<0||dv[i].y+d>=c)
            insert(i+501,1000,inf); //能跳出边界的有高度的柱子
    cout<<cnt-dinic()<<endl;
	return 0;
}

同一道题:poj2711这次裸敲dinic,呵呵!

Leapin' Lizards
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 1567 Accepted: 623

Description

Your platoon of wandering lizards has entered a strange room in the labyrinth you are exploring. As you are looking around for hidden treasures, one of the rookies steps on an innocent-looking stone and the room's floor suddenly disappears! Each lizard in your platoon is left standing on a fragile-looking pillar, and a fire begins to rage below... 

Leave no lizard behind! Get as many lizards as possible out of the room, and report the number of casualties. 

The pillars in the room are aligned as a grid, with each pillar one unit away from the pillars to its east, west, north and south. Pillars at the edge of the grid are one unit away from the edge of the room (safety). Not all pillars necessarily have a lizard. A lizard is able to leap onto any unoccupied pillar that is within d units of his current one. A lizard standing on a pillar within leaping distance of the edge of the room may always leap to safety... but there's a catch: each pillar becomes weakened after each jump, and will soon collapse and no longer be usable by other lizards. Leaping onto a pillar does not cause it to weaken or collapse; only leaping off of it causes it to weaken and eventually collapse. Only one lizard may be on a pillar at any given time.

Input

The input file will begin with a line containing a single integer representing the number of test cases, which is at most 25. Each test case will begin with a line containing a single positive integer n representing the number of rows in the map, followed by a single non-negative integer d representing the maximum leaping distance for the lizards. Two maps will follow, each as a map of characters with one row per line. The first map will contain a digit (0-3) in each position representing the number of jumps the pillar in that position will sustain before collapsing (0 means there is no pillar there). The second map will follow, with an 'L' for every position where a lizard is on the pillar and a '.' for every empty pillar. There will never be a lizard on a position where there is no pillar. 

Each input map is guaranteed to be a rectangle of size n x m, where 1 <= n <= 20 and 1 <= m <= 20. The leaping distance is always 1 <= d <= 3.

Output

For each input case, print a single line containing the number of lizards that could not escape. The format should follow the samples provided below.

Sample Input

4
3 1
1111
1111
1111
LLLL
LLLL
LLLL
3 2
00000
01110
00000
.....
.LLL.
.....
3 1
00000
01110
00000
.....
.LLL.
.....
5 2
00000000
02000000
00321100
02000000
00000000
........
........
..LLLL..
........
........

Sample Output

Case #1: 2 lizards were left behind.
Case #2: no lizard was left behind.
Case #3: 3 lizards were left behind.
Case #4: 1 lizard was left behind.

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#define Maxn 1210
using namespace std;

const int inf=0x3f3f3f3f;
struct point{
    int x,y,w;
    point(int xx,int yy,int ww):x(xx),y(yy),w(ww){}
};
struct line{
    int to,next,cap;
}p[640010];
int tot,src,t;
int head[Maxn],d[Maxn],q[Maxn];
char s[30][30];
int vis[30][30];
vector<point> dv;
void addedge(int a,int b,int c){
    p[tot].to=b;
    p[tot].next=head[a];
    p[tot].cap=c;
    head[a]=tot++;
}
void insert(int a,int b,int c){
    addedge(a,b,c);
    addedge(b,a,0);
}
bool bfs(){
    memset(d,-1,sizeof d);
    d[src]=0;
    int s=0,e=-1;
    q[++e]=src;
    while(s<=e){
        int u=q[s++];
        for(int i=head[u];i!=-1;i=p[i].next){
            int v=p[i].to;
            if(d[v]==-1&&p[i].cap){
                d[v]=d[u]+1;
                q[++e]=v;
            }
        }
    }
    return d[t]!=-1;
}
int dfs(int u,int alpha){
    if(u==t) return alpha;
    int w,used=0;
    for(int i=head[u];i!=-1&&used<alpha;i=p[i].next){
        int v=p[i].to;
        if(d[v]==d[u]+1&&p[i].cap){
            w=dfs(v,min(alpha-used,p[i].cap));
            used+=w;
            p[i].cap-=w;
            p[i^1].cap+=w;
        }
    }
    if(!used) d[u]=-1;
    return used;
}
int dinic(){
    int ans=0;
    src=0,t=1000;
    while(bfs())
        ans+=dfs(src,inf);
    return ans;
}
bool dis(int i,int j,int d){
    return (dv[i].x-dv[j].x)*(dv[i].x-dv[j].x)+
    (dv[i].y-dv[j].y)*(dv[i].y-dv[j].y)<=d*d;
}
int main()
{
    int test,r,c,d,cas=1;
    cin>>test;
    while(test--){
        tot=0;
        memset(head,-1,sizeof head);
        printf("Case #%d: ",cas++);
        cin>>r>>d;
        c=0;
        dv.clear();
        for(int i=0;i<r;i++){
            scanf("%s",s[i]);
            for(int j=0;s[i][j];j++){
                if(i==0) c++;
                if(s[i][j]!='0')
                    dv.push_back(point(i,j,s[i][j]-'0'));
            }
        }
        int cnt=0;
        memset(vis,0,sizeof vis);
        for(int i=0;i<r;i++){
            scanf("%s",s[i]);
            for(int j=0;s[i][j];j++)
                if(s[i][j]=='L'){
                    vis[i][j]=1;
                    cnt++;
                }
        }
        for(int i=0;i<dv.size();i++){
            if(vis[dv[i].x][dv[i].y]) insert(0,i+1,1);
            insert(i+1,i+501,dv[i].w);
        }
        for(int i=0;i<dv.size();i++)
            for(int j=0;j<dv.size();j++)
                if(i!=j&&dis(i,j,d)) insert(i+501,j+1,inf);
        for(int i=0;i<dv.size();i++)
            if(dv[i].x-d<0||dv[i].x+d>=r||dv[i].y-d<0||dv[i].y+d>=c)
                insert(i+501,1000,inf);
        int res=dinic();
        if(res==cnt) printf("no lizard was left behind.\n");
        else if(cnt-res==1) printf("%d lizard was left behind.\n",cnt-res);
        else printf("%d lizards were left behind.\n",cnt-res);
    }
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BZOJ 2908 题目是一个数据下载任务。这个任务要求下载指定的数据文件,并统计文件中小于等于给定整数的数字个数。 为了完成这个任务,首先需要选择一个合适的网址来下载文件。我们可以使用一个网络爬虫库,如Python中的Requests库,来帮助我们完成文件下载的操作。 首先,我们需要使用Requests库中的get()方法来访问目标网址,并将目标文件下载到我们的本地计算机中。可以使用以下代码实现文件下载: ```python import requests url = '目标文件的网址' response = requests.get(url) with open('本地保存文件的路径', 'wb') as file: file.write(response.content) ``` 下载完成后,我们可以使用Python内置的open()函数打开已下载的文件,并按行读取文件内容。可以使用以下代码实现文件内容读取: ```python count = 0 with open('本地保存文件的路径', 'r') as file: for line in file: # 在这里实现对每一行数据的判断 # 如果小于等于给定整数,count 加 1 # 否则,不进行任何操作 ``` 在每一行的处理过程中,我们可以使用split()方法将一行数据分割成多个字符串,并使用int()函数将其转换为整数。然后,我们可以将该整数与给定整数进行比较,以判断是否小于等于给定整数。 最后,我们可以将统计结果打印出来,以满足题目的要求。 综上所述,以上是关于解决 BZOJ 2908 数据下载任务的简要步骤和代码实现。 希望对您有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值