poj 3422 洛谷P2045 K取方格數(方格取數加強版)
阿新 • • 發佈:2018-04-01
open output bsp pac tput ons upd continue tdi
Description:
給出一個n*n的矩陣,每一格有一個非負整數Aij,(Aij <= 1000)現在從(1,1)出發,可以往右或者往下走,最後到達(n,n),每達到一格,把該格子的數取出來,該格子的數就變成0,這樣一共走K次,現在要求K次所達到的方格的數的和最大
Input:
第一行兩個數n,k(1<=n<=50, 0<=k<=10)
接下來n行,每行n個數,分別表示矩陣的每個格子的數
Output:
一個數,為最大和
思路:仍舊是拆點 因為每個點都有一個限制K和一個價值V 所以將一個點拆成兩個點,對相鄰的點連兩條邊,一條費用為V,限制為1, 一條費用為0,限制為K - 1。然後跑個最大費用最大流即可
#include<iostream> #include<cstring> #include<queue> using namespace std; const int N = 50100, M = 2000100; int d[N], incf[N], pre[N], n, k, s, t, maxflow, ans; bool vis[N]; int head[N],now; struct edges{ int to,next,lim,w; }edge[N<<1]; void add(int x,int y,intView Codez,int c){ edge[++now] = {y,head[x],z,c}; head[x] = now; edge[++now] = {x,head[y],0,-c}; head[y] = now; } int id(int i,int j,int k){ return (i - 1)*n + j + k * n * n;} bool spfa(){ queue<int> q; memset(d,0xcf,sizeof(d)); memset(vis,0,sizeof(vis)); q.push(s); d[s]= 0; vis[s] = 1; incf[s] = 1e9; while(!q.empty()){ int x = q.front(); vis[x] = 0; q.pop(); for(int i = head[x]; i; i = edge[i].next){ int v = edge[i].to; if(!edge[i].lim) continue; if(d[v] < d[x] + edge[i].w){ d[v] = d[x] + edge[i].w; incf[v] = min(incf[x], edge[i].lim); pre[v] = i; if(!vis[v]) vis[v] = 1, q.push(v); } } } if(d[t] == 0xcfcfcfcf) return 0; return 1; } void update(){ int x = t; while(x != s){ int i = pre[x]; edge[i].lim -= incf[t]; edge[i ^ 1].lim += incf[t]; x = edge[i ^ 1].to; } maxflow += incf[t]; ans += d[t] * incf[t]; } int main(){ ios::sync_with_stdio(false); cin>>n>>k; s = 1, t = 2*n*n; now = 1; int x; for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++){ cin>>x; add(id(i,j,0),id(i,j,1),1,x); add(id(i,j,0),id(i,j,1),k - 1,0); if(j < n) add(id(i,j,1),id(i,j+1,0),k,0); if(i < n) add(id(i,j,1),id(i+1,j,0),k,0); } while(spfa()) update(); cout<<ans<<endl; return 0; }
poj 3422 洛谷P2045 K取方格數(方格取數加強版)