jzoj5057-[GDSOI2017模拟4.13]炮塔【网络流,最大权闭合图】
生活随笔
收集整理的這篇文章主要介紹了
jzoj5057-[GDSOI2017模拟4.13]炮塔【网络流,最大权闭合图】
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
正題
題面鏈接:https://gmoj.net/senior/#main/show/5057
題目大意
n?mn*mn?m的網(wǎng)格上有一些炮和敵軍,每個(gè)炮可以攻擊在它方向上一個(gè)敵軍,但是要求炮彈的軌跡不能交叉。求最多打死多少敵軍。
解題思路
我們先把炮分成兩類,一類是橫著打(定義為正類),一類是豎著打(定義為負(fù)類),那么肯定是兩類不同的軌跡交叉。
我們對(duì)于每個(gè)炮彈,它每走一格,可能能夠多打一些敵方,我們可以把這個(gè)多大的定義為這個(gè)點(diǎn)的權(quán)值。顯然對(duì)于每一類,格子都會(huì)有一個(gè)權(quán)值。
然后我們大致構(gòu)建一個(gè)這樣的圖(炮1的第二個(gè)與炮2的第二個(gè)有交叉)
- 割掉權(quán)值為www(這里的www統(tǒng)指那個(gè)點(diǎn)在那一類的權(quán)值)的邊表示不選擇這個(gè)點(diǎn)
- 正類的邊連向炮的方向是因?yàn)槿绻覀円尳徊娴哪菞l邊不生效,也就是要把后面三個(gè)的www權(quán)值舍棄,那么就表示炮彈不會(huì)打到后面那三個(gè)
- 反類的邊從炮彈出去也是一個(gè)原理,我們要求舍去的一定是一個(gè)后綴
然后這就是一個(gè)經(jīng)典的最大權(quán)閉合圖模板了,上網(wǎng)絡(luò)流即可。
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int N=6000,inf=2147483647/3; const int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1}; struct node{int to,next,w; }a[N<<8]; int n,m,tot,s,t,cnt,ans; int dep[N],ls[N]; int v[51][51],wv[51][51]; queue<int> q; void addl(int x,int y,int w){if(!w)return;a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;a[tot].w=w;a[++tot].to=x;a[tot].next=ls[y];ls[y]=tot;a[tot].w=0;return; } bool bfs(){memset(dep,0,sizeof(dep));dep[s]=1;while(!q.empty())q.pop();q.push(s);while(!q.empty()){int x=q.front();q.pop();for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(dep[y]||!a[i].w)continue;dep[y]=dep[x]+1;if(y==t)return 1;q.push(y);}}return 0; } int dinic(int x,int flow){int rest=0,k;if(x==t)return flow;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(dep[x]+1!=dep[y]||!a[i].w)continue;rest+=(k=dinic(y,min(flow-rest,a[i].w)));a[i].w-=k;a[i^1].w+=k;if(rest==flow)return flow;}if(!rest)dep[x]=0;return rest; } int main() {scanf("%d%d",&n,&m);s=0;t=cnt=tot=1;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%d",&wv[i][j]);for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){int tmp=0,x=i,y=j;if(wv[x][y]<0){int k=-wv[x][y]-1,last=++cnt,tmpp=0;if(k>1)continue;while(1){x+=dx[k];y+=dy[k];if(x<1||y<1||x>n||y>m)break;tmp=max(tmp,wv[x][y]);cnt++;addl(s,cnt,tmp-tmpp);if(last)addl(cnt,last,inf);tmpp=tmp;last=v[x][y]=cnt;}ans+=tmp;}}for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){int tmp=0,x=i,y=j;if(wv[x][y]<0){int k=-wv[x][y]-1,last=++cnt,tmpp=0;if(k<2)continue;while(1){x+=dx[k];y+=dy[k];if(x<1||y<1||x>n||y>m)break;tmp=max(tmp,wv[x][y]);cnt++;addl(cnt,t,tmp-tmpp);if(last)addl(last,cnt,inf);if(v[x][y])addl(v[x][y],cnt,inf);tmpp=tmp;last=cnt;}ans+=tmp;}}while(bfs())ans-=dinic(s,inf);printf("%d\n",ans);return 0; }總結(jié)
以上是生活随笔為你收集整理的jzoj5057-[GDSOI2017模拟4.13]炮塔【网络流,最大权闭合图】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ddos ping(无限ping是ddo
- 下一篇: [2020.11.25NOIP模拟赛]下