您的位置:首页 > 其它

洛谷 1004 dp或最大费用流

2015-09-01 12:34 405 查看
思路:

dp方法:

    设dp[i][j][k][l]为两条没有交叉的路径分别走到(i,j)和(k,l)处最大价值。

    则转移方程为

    dp[i][j][k][l]=max(dp[i-1][j][k-1][l],dp[i][j-1][k-1][l],dp[i-1][j][k][l-1],dp[i][j-1][k][l-1])+map[i][j]+map[k][l];

    若两点相同减去一个map[i][j]即可

费用流方法(可以扩展为k条路径,但时间复杂度较高):

    源点连接左上角点流量为k、费用为0,右下角点连接汇点流量为k、费用为0,所有点连接右边相邻和下边相邻点流量为k、费用为0,所有点拆点一条流量为1、费用为该

    点价值,一条流量为k-1、费用为0。跑最大费用流即可

代码:

dp:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
#include <set>
using namespace std;

#define N 205
#define M 1005
#define inf 999999999

struct MCF{//min_cost_flow
struct Edge{
int v, f, w, next;
Edge(){};
Edge(int a,int b,int c,int d){
v=a;f=b;w=c;next=d;
}
};
int n;
int head[N+10];
Edge e[M*2];
int nume;
int src, sink;

void init(int st, int end,int nn){//初始化
src=st;sink=end;n=nn;
memset(head,0,sizeof(head));
nume=1;
}

void addedge(int u,int v,int c,int w){
e[++nume]=Edge(v,c,w,head[u]);
head[u]=nume;
e[++nume]=Edge(u,0,-w,head[v]);
head[v]=nume;
}

queue<int>Q;
bool visited
;
int dis
;
int prev
, pree
;

bool findpath(){

while(!Q.empty()) Q.pop();
Q.push(src);
for(int i=0;i<=n;i++) dis[i]=-1;
dis[src]=0;
visited[src]=true;
while(!Q.empty()){
int u=Q.front();Q.pop();visited[u]=false;
for(int i=head[u];i;i=e[i].next){
if(e[i].f>0&&dis[u]+e[i].w>dis[e[i].v]){
dis[e[i].v]=dis[u]+e[i].w;
prev[e[i].v]=u;
pree[e[i].v]=i;
if(!visited[e[i].v]){
Q.push(e[i].v);
visited[e[i].v]=true;
}
}
}
}//printf("111111\n");
if(dis[sink]>0) return true;
else return false;
}

int solve(){

int u=sink;
int flow=inf;
while(u!=src){
if(e[pree[u]].f<flow) flow=e[pree[u]].f;
u=prev[u];
}
u=sink;
while(u!=src){
e[pree[u]].f-=flow;
e[pree[u]^1].f+=flow;
u=prev[u];
}

return dis[sink]*flow;
}

int mincostflow(){
int ans=0;
while(findpath()){
ans+=solve();
}
return ans;
}
}mcf;

int n;
int map[10][10];

int x, y, w;

main()
{
int i, j, k;
while(scanf("%d",&n)==1){
memset(map,0,sizeof(map));
while(1){

scanf("%d %d %d",&x,&y,&w);
if(x==0&&y==0&&w==0) break;
map[x][y]=w;
}
mcf.init(0,n*n*2+1,n*n*2+2);
mcf.addedge(0,1,2,0);
mcf.addedge(n*n*2,n*n*2+1,2,0);
int temp=1;
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
mcf.addedge(temp,temp+n*n,1,map[i][j]);
mcf.addedge(temp,temp+n*n,1,0);
if(i<n) mcf.addedge(temp+n*n,temp+n,2,0);
if(j<n) mcf.addedge(temp+n*n,temp+1,2,0);
temp++;
}
}
printf("%d\n",mcf.mincostflow());
}
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: