原来这种题的解法是费用流。

从一个方格的左上走到右下,最多走k次,每个数最多拿走一次。

每次走动的流量设为1,起始点拆点成限制流量k。

每个点拆成两条路,一条路限制流量1,费用为价值相反数。另一条路无限流量。

跑一遍费用流。

#include<bits/stdc++.h>
using namespace std; const int MAXN=+;
const int MAXM=;
const int INF=0x3f3f3f3f;
struct Edge{
int to,next,cap,flow,cost;
}edge[MAXM];
int head[MAXN],tol;
int pre[MAXN],dis[MAXN];
bool vis[MAXN]; int n;
void init(){
tol=;
memset(head,-,sizeof(head));
} void addedge(int u,int v,int cap,int cost){
edge[tol].to=v;
edge[tol].cap=cap;
edge[tol].cost=cost;
edge[tol].flow=;
edge[tol].next=head[u];
head[u]=tol++; edge[tol].to=u;
edge[tol].cap=;
edge[tol].cost=-cost;
edge[tol].flow=;
edge[tol].next=head[v];
head[v]=tol++;
} bool spfa(int s,int t){
queue<int> q;
memset(dis,INF,sizeof(dis));
memset(vis,false,sizeof(vis));
memset(pre,-,sizeof(pre)); dis[s]=;
vis[s]=true;
q.push(s);
while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=false;
for(int i=head[u];i!=-;i=edge[i].next){
int v=edge[i].to;
if(edge[i].cap>edge[i].flow&&dis[v]>dis[u]+edge[i].cost){
dis[v]=dis[u]+edge[i].cost;
pre[v]=i;
if(!vis[v]){
vis[v]=true;
q.push(v);
}
}
}
}
if(pre[t]==-)
return false;
else
return true;
} int minCostMaxFlow(int s,int t,int &cost){
int flow=;
cost=;
while(spfa(s,t)){
int Min=INF;
for(int i=pre[t];i!=-;i=pre[edge[i^].to]){
if(Min>edge[i].cap-edge[i].flow)
Min=edge[i].cap-edge[i].flow;
}
for(int i=pre[t];i!=-;i=pre[edge[i^].to]){
edge[i].flow+=Min;
edge[i^].flow-=Min;
cost+=edge[i].cost*Min;
}
flow+=Min;
}
return flow;
} void show(int s){
bool vis[];
queue<int> q;
vis[s]=;
q.push(s);
while(!q.empty()){
int u=q.front();
q.pop();
cout<<"u="<<u<<endl;
for(int i=head[u];i!=-;i=edge[i].next){
int v=edge[i].to;
if(vis[v]==){
vis[v]=;
q.push(v);
}
}
}
cout<<endl;
} /* EK end */ int a[][]; int k; inline int getid(int i,int j,int isout){
return (i-)*n+j+isout*(n*n);
} int main(){
init();
scanf("%d%d",&n,&k); int si=*n*n+,so=*n*n+;
addedge(si,so,k,);//最多走k次
int t=*n*n+; for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
int c;
scanf("%d",&c);
addedge(getid(i,j,),getid(i,j,),,-c);
//拿走它,获得价值,费用是相反数
addedge(getid(i,j,),getid(i,j,),INF,);
//不拿就不拿呗
}
} for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
if(i+<=n)
addedge(getid(i,j,),getid(i+,j,),INF,);
if(j+<=n)
addedge(getid(i,j,),getid(i,j+,),INF,);
}
} addedge(so,getid(,,),INF,);
addedge(getid(n,n,),t,INF,); //show(si); int cost=;
int flow=minCostMaxFlow(si,t,cost);
printf("%d\n",-cost); }

最新文章

  1. My97 DatePicker 日期选择插件.
  2. code first提示已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭解决方法
  3. C#处理猜拳问题(非窗体)
  4. 云,git,blog,感想
  5. PBOC规范(2.0-&gt;3.0)对照表
  6. 剑指OFFER之包含min函数的栈(九度OJ1522)
  7. mysql 中执行的 sql 注意字段之间的反向引号和单引号
  8. *1022. D进制的A+B【考前最后一道题】
  9. LindDotNetCore~授权中间件的介绍
  10. 一、关于a标签伪类中的visited不起作用问题
  11. 【XSY2771】城市 分治
  12. Linux 的基本操作(文件与目录管理)
  13. UVA725 Division 除法【暴力】
  14. 约数,gcd,exgcd.
  15. git回退代码到某次commit
  16. PAT 1011 World Cup Betting
  17. C语言面试题1
  18. 《Effective Java》读书笔记七(通用程序设计)
  19. jQuery 隐藏与显示 input 默认值
  20. springboot 默认错误处理--自定义

热门文章

  1. uwsgi 热启动
  2. go使用时间作为种子生成随机数
  3. jdk与jre安装之后的名字
  4. RPM安装mysql5.6
  5. Variable &#39;bop&#39; is uninitialized when captured by block
  6. unity常见问题之20题
  7. 使用 C# 开发智能手机软件:推箱子(四)
  8. iOS Webview 与 app交互
  9. Codeforces Round #262 (Div. 2)460A. Vasya and Socks(简单数学题)
  10. 移动Web开发实践