P2045 方格取数加强版

P2045 方格取数加强版

题目描述

给出一个 n×n 的矩阵,每一格有一个非负整数 Ai,jAi,j103),现在从 (1,1) 出发,可以往右或者往下走,最后到达 (n,n),每达到一格,把该格子的数取出来,该格子的数就变成 0,这样一共走 K 次,现在要求 K 次所达到的方格的数的和最大。

Solution:

有且仅有一点思维难度的费用题,我们考虑拆点来维护每个格子上的数只能被取一次和流量限制:

uinuout 连一条费用为 au , 流量为 1 的边。

uinuout 连一条费用为 0 ,流量为 K1 的边。

然后再按题意将 uout 向他的邻居的 in 连边就好了。

Code:

#include<bits/stdc++.h>
const int M=55;
const int N=M*M*2;
const int inf=1e9;
using namespace std;
int a[M][M];
int n,m,S,T,ans,cnt=1;
struct Edge{
int to,w,fl,nxt;
}e[N<<2];int head[N];
inline void add(int x,int y,int w,int fl)
{
e[++cnt]={y,w,fl,head[x]};head[x]=cnt;
e[++cnt]={x,-w,0,head[y]};head[y]=cnt;
}
inline int id(int i,int j){return (i-1)*n+j;}
inline int idd(int i,int j){return n*n+id(i,j);}
int dis[N],dl[N],flow[N],pre[N];
inline void init()
{
for(int u=0;u<=T;u++)dis[u]=-inf,flow[u]=0;
}
queue<int> Q;
bool spfa(int s,int t)
{
init();flow[s]=m;dis[s]=0;
Q.push(s);
while(!Q.empty())
{
int u=Q.front();Q.pop();dl[u]=0;
for(int i=head[u],v,w,fl;i;i=e[i].nxt)
{
v=e[i].to,w=e[i].w,fl=e[i].fl;
if(fl&&dis[v]<dis[u]+w)
{
dis[v]=dis[u]+w;flow[v]=min(fl,flow[u]);
if(!dl[v])Q.push(v);pre[v]=i;
}
}
}
return dis[t]!=-inf;
}
void dinic()
{
while(spfa(S,T))
{
int now=T,id,res=0;
ans+=dis[T];
while(now!=S)
{
id=pre[now];e[id].fl--;e[id^1].fl++;now=e[id^1].to;
}
}
}
void work()
{
cin>>n>>m;S=1,T=idd(n,n);
for(int i=1,x;i<=n;i++)for(int j=1;j<=n;j++)
{
scanf("%d",&x);
add(id(i,j),idd(i,j),x,1);
add(id(i,j),idd(i,j),0,m-1);
if(i+1<=n)add(idd(i,j),id(i+1,j),0,m);
if(j+1<=n)add(idd(i,j),id(i,j+1),0,m);
}
dinic();
cout<<ans;
}
int main()
{
//freopen("P2045.in","r",stdin);freopen("P2045.out","w",stdout);
work();
return 0;
}
posted @   liuboom  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示