K取方格数
给定矩阵 从1,1到n~m设计k条线路 取走格子中的数(重复经过只取一次)k条线路和的最大值是多少
技巧:
- 每个点拆成入点和出点 实现点边的转化
- 通过限制费用大小和流量大小 来实现被取走的次数和贡献
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
const int N=55;
const double eps=1e-9;
const int INF=0x3f3f3f3f;
int read()
{
int x=0,f=0,c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return f?-x:x;
}
struct Edge
{
int to,next,w,c;
}e[N*N*8];
int head[N*N*2],cnt=1;
void _add(int a,int b,int c,int d){e[++cnt]=(Edge){b,head[a],c,d};head[a]=cnt;}
void add(int a,int b,int c,int d){
//printf("%d %d %d %d\n",a,b,c,d);
_add(a,b,c,d); _add(b,a,0,-d);}
int maxflow,ans,n,s,t,k;
int F(int x,int y,int z){ return (x-1)*n+y+z*n*n; }
queue<int> q;
bool inq[N*N*2];
int d[N*N*2],incf[N*N*2],pre[N*N*2];
//spfa 多次拓展 但是进入队列只有一次
bool spfa()
{
while(q.size()) q.pop();
memset(inq,0,sizeof inq); memset(d,0xcf,sizeof d);
q.push(1); inq[1]=1; incf[1]=INF; d[1]=0;
while(q.size())
{
int x=q.front(); q.pop(); inq[x]=0;//注意出队标记
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].to;
if(!e[i].w) continue;
if(d[y]<d[x]+e[i].c)
{
d[y]=d[x]+e[i].c;
incf[y]=min(incf[x],e[i].w); pre[y]=i;
if(!inq[y]) inq[y]=1,q.push(y);//注意入队标记
}
}
}
return d[t]!=0xcfcfcfcf;
}
void update()
{
int x=t;
while(x!=s)
{
int i=pre[x];
e[i].w-=incf[t]; e[i^1].w+=incf[t];
x=e[i^1].to;
}
maxflow+=incf[t];
ans+=d[t]*incf[t];
}
int main()
{
n=read(); k=read();
s=1; t=n*n*2;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
int x=read();
add(F(i,j,0),F(i,j,1),1,x); add(F(i,j,0),F(i,j,1),k-1,0);
if(j<n) add(F(i,j,1),F(i,j+1,0),k,0);
if(i<n) add(F(i,j,1),F(i+1,j,0),k,0);
}
while(spfa()) update();
printf("%d",ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现