1. 程式人生 > >codevs 1227 方格取數 2

codevs 1227 方格取數 2

ble struct min 現在 blank 數據 name body icon

時間限制: 1 s 空間限制: 128000 KB 題目等級 : 大師 Master 題目描述 Description

給出一個n*n的矩陣,每一格有一個非負整數Aij,(Aij <= 1000)現在從(1,1)出發,可以往右或者往下走,最後到達(n,n),每達到一格,把該格子的數取出來,該格子的數就變成0,這樣一共走K次,現在要求K次所達到的方格的數的和最大

輸入描述 Input Description

第一行兩個數n,k(1<=n<=50, 0<=k<=10)

接下來n行,每行n個數,分別表示矩陣的每個格子的數

輸出描述 Output Description

一個數,為最大和

樣例輸入 Sample Input

3 1

1 2 3

0 2 1

1 4 2

樣例輸出 Sample Output

11

數據範圍及提示 Data Size & Hint

1<=n<=50, 0<=k<=10

拆點+費用流

把每個點拆成兩個 x,y

x,y之間建兩條邊

第一條 流量為1 費用為點值

第二條 流量inf 費用0

目的是表示 可以經過無數次,但價值只能取一次

屠龍寶刀點擊就送

#include <ctype.h>
#include 
<cstdio> #include <queue> #define N 100000 #define inf 0x7ffffff using namespace std; void read(int &x) { x=0;bool f=0; register char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch==-) f=1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-0; } struct Edge { int
next,to,value,flow; Edge (int next=0,int to=0,int flow=0,int value=0) : next(next),to(to),flow(flow),value(value) {} }edge[N<<1]; bool vis[N]; int flow[N],dis[N],head[N],cnt=1,fa[N],n,k,tot; void insert(int u,int v,int w,int l) { edge[++cnt]=Edge(head[u],v,w,l); head[u]=cnt; } int min(int a,int b) {return a>b?b:a;} bool spfa(int s,int t) { for(int i=s;i<=t;i++) {flow[i]=inf;dis[i]=0xefefefef;vis[i]=0;} vis[s]=1; dis[s]=0; fa[s]=0; queue<int>Q; Q.push(s); while(!Q.empty()) { int now=Q.front(); Q.pop(); vis[now]=0; for(int i=head[now];i;i=edge[i].next) { int v=edge[i].to; if(dis[v]<edge[i].value+dis[now]&&edge[i].flow>0) { dis[v]=dis[now]+edge[i].value; flow[v]=min(flow[now],edge[i].flow); fa[v]=i; if(!vis[v]) { vis[v]=1; Q.push(v); } } } } return dis[t]>0; } int dinic(int s,int t) { int sum=0; for(;spfa(s,t);) { int x=flow[t]; for(int i=t;i!=s&&i;i=edge[fa[i]^1].to) { edge[fa[i]].flow-=x; edge[fa[i]^1].flow+=x; } sum+=x*dis[t]; } return sum; } int main() { read(n); read(k); for(int i=1;i<=n;i++) { for(int a,j=1;j<=n;j++) { read(a); tot++; insert(tot*2,tot*2+1,1,a); insert(tot*2+1,tot*2,0,-a); insert(tot*2,tot*2+1,inf,0); insert(tot*2+1,tot*2,0,0); if(j!=n) { insert(tot*2+1,(tot+1)*2,inf,0); insert((tot+1)*2,tot*2+1,0,0); } if(i!=n) { insert(tot*2+1,(tot+n)*2,inf,0); insert((tot+n)*2,tot*2+1,0,0); } } } insert(1,2,k,0); insert(2,1,0,0); insert(tot*2+1,tot*2+2,k,0); insert(tot*2+2,tot*2+1,0,0); printf("%d",dinic(1,tot*2+2)); return 0; }

codevs 1227 方格取數 2