思路:最大费用最大流
AC代码:
1 #include<string.h> 2 #include<iostream> 3 #include<stdio.h> 4 #include<algorithm> 5 #include<queue> 6 #include<vector> 7 #include<map> 8 #include<cmath> 9 using namespace std; 10 #define inf 0x3f3f3f3f 11 const int N=55*55*2; 12 typedef long long ll; 13 14 struct node 15 { 16 int to,nextt; 17 int cap,flow,cost; 18 } e[N*N]; 19 20 bool book[N]; 21 int pre[10*N],head[10*N],dist[N],a[N][N]; 22 int tot,s,t; 23 24 void add(int u,int v,int cap,int cost) 25 { 26 e[tot].to=v; 27 e[tot].cap=cap; 28 e[tot].cost=cost; 29 e[tot].flow=0; 30 e[tot].nextt=head[u]; 31 32 head[u]=tot++; 33 e[tot].to=u; 34 e[tot].cap=0; 35 e[tot].cost=-cost; 36 e[tot].flow=0; 37 e[tot].nextt=head[v]; 38 head[v]=tot++; 39 } 40 41 bool SPFA() 42 { 43 for(int i=0; i<=t; i++) 44 { 45 dist[i]=inf; 46 book[i]=0; 47 pre[i]=-1; 48 } 49 book[s]=1; 50 dist[s]=0; 51 queue<int>Q; 52 Q.push(s); 53 while(!Q.empty()) 54 { 55 int u=Q.front(); 56 Q.pop(); 57 book[u]=0; 58 for(int i=head[u]; i!=-1; i=e[i].nextt) 59 { 60 int v=e[i].to; 61 if(e[i].cap>e[i].flow&&dist[v]>dist[u]+e[i].cost) 62 { 63 dist[v]=dist[u]+e[i].cost; 64 pre[v]=i; 65 if(book[v]==0) 66 { 67 book[v]=1; 68 Q.push(v); 69 } 70 } 71 } 72 } 73 if(dist[t]!=inf) 74 return 1; 75 return 0; 76 } 77 78 int MCMF() 79 { 80 int flow=0,cost=0; 81 while(SPFA()) 82 { 83 int minn=inf; 84 for(int i=pre[t]; i!=-1; i=pre[e[i^1].to]) 85 minn=min(minn,e[i].cap-e[i].flow); 86 for(int i=pre[t]; i!=-1; i=pre[e[i^1].to]) 87 { 88 e[i].flow+=minn; 89 e[i^1].flow-=minn; 90 cost+=e[i].cost*minn; 91 } 92 flow+=minn; 93 } 94 return cost; 95 } 96 97 int main() 98 { 99 int n,k; 100 while(~scanf("%d %d",&n,&k)) 101 { 102 for(int i=1;i<=n;i++) 103 { 104 for(int j=1;j<=n;j++) 105 { 106 scanf("%d",&a[i][j]); 107 } 108 } 109 tot=0; 110 memset(head,-1,sizeof(head)); 111 s=0,t=n*n*2+1;//t=n*n+1 112 /* for(int i=1; i<=n; i++) 113 { 114 for(int j=1; j<=n; j++) 115 { 116 if(i==n&&j==n) 117 continue; 118 if(i==n)//down 119 add(i+1,j,1,a[i+1][j]); 120 else if(j==n)//right 121 add(i,j+1,1,a[i][j+1]); 122 else 123 { 124 add(i,j+1,1,a[i][j+1]);//right 125 add(i+1,j,1,a[i+1][j]);//down 126 } 127 } 128 }*/ 129 for(int i=1;i<=n;i++) 130 { 131 for(int j=1;j<=n;j++) 132 { 133 int x=(i-1)*n+j; 134 add(x*2,x*2+1,1,-a[i][j]); 135 add(x*2,x*2+1,k-1,0); 136 if(j!=n)//向下 137 add(x*2+1,(x+1)*2,k,0); 138 if(i!=n)//右 139 add(x*2+1,(x+n)*2,k,0); 140 } 141 } 142 add(s,2,k,0); 143 add(2*n*n+1,t,k,0); 144 int mincost=MCMF()*(-1); 145 printf("%d\n",mincost); 146 147 } 148 return 0; 149 }