http://poj.org/problem?id=3422

题意 : 给你一个N*N的方格,每个格子有一个数字,让你从左上角开始走,只能往下往右走,走过的数字变为0,走K次,问最大能是多大,累加的。

思路 :http://blog.csdn.net/qq172108805/article/details/7857503,这道题挺难的,我也是看的题解。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <stdlib.h>
#include <algorithm>

using namespace std;

const int maxn = 5050 ;
const int INF = 1000000000 ;
const int maxm = 110000 ;

struct node
{
    int u,v,c,f,b,next ;
}map[maxm] ;
bool flag[maxn] ;
int cap[55][55],dist[maxn],pre[maxn],head[maxn] ;
int s,t,n,k,ans,cnt ;
int del,val ;

void addedge(int u,int v,int c,int b)
{
    map[cnt].u = u ;
    map[cnt].v = v ;
    map[cnt].c = c ;
    map[cnt].b = b ;
    map[cnt].f = 0 ;
    map[cnt].next = head[u] ;
    head[u] = cnt++ ;

    map[cnt].u = v ;
    map[cnt].v = u ;
    map[cnt].c = 0 ;
    map[cnt].b = -b ;
    map[cnt].f = 0 ;
    map[cnt].next = head[v] ;
    head[v] = cnt++ ;
}

void spfa()
{
    memset(flag,0,sizeof(flag)) ;
    queue<int >Q ;
    Q.push(s) ;
    flag[s] = true ;
    while(!Q.empty())
    {
        int x = Q.front() ;
        Q.pop() ;
        flag[x] = false ;
        for(int i = head[x] ; i+1 ; i = map[i].next)
        {
            int y = map[i].v ;
            if(map[i].c > map[i].f && dist[y] < dist[x] + map[i].b)
            {
                dist[y] = dist[x]+map[i].b ;
                pre[y] = i ;
                if(!flag[y])
                {
                    flag[y] = true ;
                    Q.push(y) ;
                }
            }
        }
    }
}

void mcmf()
{
    for( ; ; )
    {
        memset(dist,-1,sizeof(dist)) ;
        memset(pre,-1,sizeof(pre)) ;
        dist[s] = 0 ;
        spfa() ;
        if(dist[t] == -1)
        break ;
        int minn = INF ;
        for(int i = pre[t] ; i+1 ; i = pre[map[i].u])
        minn = min(minn,map[i].c-map[i].f) ;
        for(int i = pre[t] ; i+1 ; i = pre[map[i].u])
        {
            map[i].f += minn ;
            map[i^1].f -= minn ;
        }
        ans += dist[t] ;
    }
}

void Init()
{
    cnt = 0 ;
    memset(head,-1,sizeof(head)) ;
    s = 0 ;
    t = 2*n*n+1 ;
    del = n*n ;
    ans = 0 ;
}
int main()
{
    scanf("%d %d",&n,&k) ;
    Init() ;
    for(int i = 1 ; i <= n ; i++)
    {
        for(int j = 1 ; j <= n ; j++)
        scanf("%d",&cap[i][j]) ;
    }
    addedge(s,1,k,0) ;
    addedge(n*n+del,t,k,0) ;
    for(int i = 1 ; i <= n ; i++)
    {
        for(int j = 1 ; j <= n ; j++)
        {
            val = (i-1)*n+j ;
            addedge(val,val+del,1,cap[i][j]) ;
            addedge(val,val+del,INF,0) ;
            if(j != n) addedge(val+del,val+1,INF,0) ;
            if(i < n) addedge(val+del,val+n,INF,0) ;
        }
    }
    mcmf() ;
    printf("%d\n",ans) ;
    return 0;
}
View Code

 

 

posted on 2014-02-11 16:52  枫、  阅读(154)  评论(0编辑  收藏  举报