[bzoj1565]植物大战僵尸

Input

Output

仅包含一个整数,表示可以获得的最大能源收入。注意,你也可以选择不进行任何攻击,这样能源收入为0。

Sample Input

3 2

10 0

20 0

-10 0

-5 1 0 0

100 1 2 1

100 0

Sample Output

25

Hint

在样例中, 植物P1,1可以攻击位置(0,0), P2, 0可以攻击位置(2,1)。 
一个方案为,首先进攻P1,1, P0,1,此时可以攻击P0,0 。共得到能源收益为(-5)+20+10 = 25。注意, 位置(2,1)被植物P2,0保护,所以无法攻击第2行中的任何植物。 
【大致数据规模】
约20%的数据满足1 ≤ N, M ≤ 5;
约40%的数据满足1 ≤ N, M ≤ 10;
约100%的数据满足1 ≤ N ≤ 20,1 ≤ M ≤ 30,-10000 ≤ Score ≤ 10000 。

最大权闭合子图问题。

此类问题为:有n个点,每个点有一个权值(可以为负数),选某个点就要先选其它的一些点。求最大收益。

此类问题的一般性解法为:

1.用拓扑排序把永远选不了的点删掉。

2.若第i个点需要先选第j个点,则连一条(i,j,inf)的边。

3.如果该点点权为正,则连一条(S,i,val)的边。

4.否则连一条(i,T,-val)的边

5.最后答案为所有正权点的权值总和-最大流。

具体参见:https://www.2cto.com/kf/201611/563122.html

对于此题,显然,对于每个点,它能防御到的 每一行的最前面的点 的后面的点 都是要先选这个点的。

即设绿点能防御到所有黄点,那么要选所有红色区域就要先选绿点。

然后就做完了。

#include<iostream>
#include<cstring>
#include<cstdio>
#define no(r,c) r*m+c+1
#define inf 2e9+7
using namespace std;
int front[50];bool used[2000];
int into[2000],que[2000000],HH=0,TT=0;
int h[500000],nxt[1000000],to[1000000],cap[1000000],TOT=0;
int mp[50][50],x[500000],y[500000];
int S,T,level[2000],iter[2000];
void ins(int u,int v){nxt[++TOT]=h[u];h[u]=TOT;to[TOT]=v;}
void ins2(int u,int v,int c){nxt[++TOT]=h[u];h[u]=TOT;to[TOT]=v;cap[TOT]=c;nxt[++TOT]=h[v];h[v]=TOT;to[TOT]=u;cap[TOT]=0;}
bool bfs()
{
    memset(level,0,sizeof(level));
    int HH=0,TT=0;
    que[TT++]=S;level[S]=1;
    while(HH<TT)
    {
        int u=que[HH++];
        for(int i=h[u];i;i=nxt[i])
        {
            int v=to[i];
            if(cap[i]&&!level[v]){level[v]=level[u]+1;que[TT++]=v;}
        }
    }
    return level[T]?true:false;
}
int dfs(int u,int f)
{
    if(u==T)return f;
    int used=0;
    for(int &i=iter[u];i;i=nxt[i])
    {
        int v=to[i];if(!cap[i]||level[v]!=level[u]+1)continue;
        int w=dfs(v,min(cap[i],f-used));
        if(w)
        {
            cap[i]-=w;cap[i^1]+=w;
            used+=w;if(used==f)return f;
        }
    }
    return used;
}
int dinic()
{
    int flow=0;
    while(bfs()){for(int i=1;i<=2000;i++)iter[i]=h[i];flow+=dfs(S,inf);}
    return flow;
}
int main()
{
    int n,m,tot=0;scanf("%d%d",&n,&m);S=n*m+1,T=n*m+2;
    for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)
    {
        int w;scanf("%d%d",&mp[i][j],&w);
        memset(front,-1,sizeof(front));
        for(int k=1;k<=w;k++)
        {
            int r,c;scanf("%d%d",&r,&c);
            front[r]=max(front[r],c);
        }
        front[i]=max(front[i],j-1);
        for(int r=0;r<n;r++)
        for(int c=0;c<=front[r];c++){x[++tot]=no(i,j);y[tot]=no(r,c);ins(no(i,j),no(r,c));into[no(r,c)]++;}
    }
    for(int i=1;i<=n*m;i++)if(!into[i])que[TT++]=i;
    while(HH<=TT){int u=que[HH++];used[u]=1;for(int i=h[u];i;i=nxt[i])if(!(--into[to[i]]))que[TT++]=to[i];}
    memset(h,0,sizeof(h));memset(nxt,0,sizeof(nxt));memset(to,0,sizeof(to));TOT=1;
    int sum=0;
    for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)
        if(used[no(i,j)])
            if(mp[i][j]>0)ins2(S,no(i,j),mp[i][j]),sum+=mp[i][j];
            else ins2(no(i,j),T,-mp[i][j]);
    for(int i=1;i<=tot;i++)if(used[x[i]]&&used[y[i]])ins2(y[i],x[i],inf);
    printf("%d",sum-dinic());
    return 0;
}

原文地址:https://www.cnblogs.com/lher/p/8414373.html

时间: 2024-08-01 09:34:48

[bzoj1565]植物大战僵尸的相关文章

[NOI2009][BZOJ1565] 植物大战僵尸

1565: [NOI2009]植物大战僵尸 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1654  Solved: 769[Submit][Status][Discuss] Description Input Output 仅包含一个整数,表示可以获得的最大能源收入.注意,你也可以选择不进行任何攻击,这样能源收入为0. Sample Input 3 2 10 0 20 0 -10 0 -5 1 0 0 100 1 2 1 100 0 Sample

NOI2009植物大战僵尸

这题应该分两步来做: 1.拓扑排序,去掉无敌点 2.求最大闭合子图 需要注意几点: 1.拓扑排序时,如果(i,j)可以攻击到(x,y),那么增加(x,y)的入度,而不是(i,j)的入度 因为入度代表着要攻击它需要事先攻击几个点 2.求最大闭合子图时,用所有的正权点-最大流 3.求最大闭合子图时,如果(i,j)可以攻击到(x,y),那么连一条边(x,y)到(i,j),容量为正无穷 因为在最大闭合子图中边(x,y)到(i,j)意味着选(x,y)就必须要选(i,j),这与实际含义相符 4.s到正权点,

98植物大战僵尸OL_僵尸迷阵

最近在玩植物大战僵尸Ol打到僵尸迷阵,打了个700分倒数第一,擦.....俗话说的好,失败是成功的妈妈,于是花了点时间写了一个小玩意,我相信下次我一定能拿第一 代码非常简单: using UnityEngine; using System.Collections; using UnityEngine.UI; public class MyScript : MonoBehaviour { // Use this for initialization void Start () { } // Upd

植物大战僵尸2天空之城安卓版发布

全体注意!一大波飞行僵尸正在接近中——中国独创版<植物大战僵尸2天空之城>安卓版终于发布了.超乎想象的空战体验.全新僵尸植物军团.独特闪电环境效果和史无前例的战舰成长系统,让你和戴夫共同肩负守卫天空之城的荣耀重任.赶紧下载游戏,加入云端激战吧. <植物大战僵尸2天空之城>安桌版上线 [中国区独有版本 打造铿锵空战体验] <植物大战僵尸2>即将迎来两周年生日,为感谢中国玩家一直以来的热情支持,EA/PopCap携手拓维游戏打造了这款中国区独有新版本<植物大战僵尸2天

原生JS实现的h5小游戏-植物大战僵尸

代码地址如下:http://www.demodashi.com/demo/12755.html 项目介绍 本项目是利用原生js实现的h5小游戏-植物大战僵尸,主要结合了一下自己对于h5小游戏的理解,结合面向对象的编程思想进行开发,在实现时使用了部分es6语法,对于es6语法不太熟悉的小伙伴可以先查阅相关资料了解一下. 如有需要,可根据自己的需求修改源码样式.源码配置属性代码,实现个性化定制. 以下为文件目录结构示意图,核心代码在js文件夹下的四个common.js.main.js.game.js

java小项目之:植物大战僵尸,这个僵尸有点冷!内附素材源码

Java小项目之:植物大战僵尸! <植物大战僵尸>是由PopCap Games开发的一款益智策略类单机游戏,于2009年5月5日发售,这款游戏可谓是无人不知无人不晓. 在我身边,上到40岁的大叔阿姨,下到7.8岁的小弟弟妹妹都听说和玩过这游戏.在以前智能手机还没流行的时候,各种黑网吧,游戏厅便有着玩这游戏的人.当3G技术现世,半智能手机和智能手机出现后,这款游戏更是如日中天,与愤怒的小鸟一起霸占了手机游戏市场(但当时估计都是盗版的). 相信有些使用b站的小伙伴,应该看过很多这样的视频: 这种视

[转]植物大战僵尸95版技术分析

植物大战僵尸95版不是原版,是由植物大战僵尸吧吧友冥谷川恋制作. 本链接只提供95版的完整压缩包和0-95版的所有exe主程序 压缩包,只玩95版的直接下载95安装包解压即可玩,如果需要玩0-94版,再下载本链接提供的主程序exe压缩包,把其它版本的主程序解压到游戏目录直接运行即可.感谢植吧“崇明人家123”制作提供0-v95僵尸得到了极大强化“我会说我这个版本的冒险一周目都过不去吗?”这个出怪模式非常刺激,需要你强大的pvz功底和运气铁桶铁门.显示隐藏关卡.允许后台运行.刺激的出怪模式.无限制

Bzoj1565 [NOI2009]植物大战僵尸

Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 2363  Solved: 1092 Description Input Output 仅包含一个整数,表示可以获得的最大能源收入.注意,你也可以选择不进行任何攻击,这样能源收入为0. Sample Input 3 2 10 0 20 0 -10 0 -5 1 0 0 100 1 2 1 100 0 Sample Output 25 HINT 在样例中, 植物P1,1可以攻击位置(0,0), P2, 0

bzoj1565【NOI2009】植物大战僵尸

1565: [NOI2009]植物大战僵尸 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 2034  Solved: 944 [Submit][Status][Discuss] Description Input Output 仅包含一个整数,表示可以获得的最大能源收入.注意,你也可以选择不进行任何攻击,这样能源收入为0. Sample Input 3 2 10 0 20 0 -10 0 -5 1 0 0 100 1 2 1 100 0 Samp