SCU3033 Destroying a Painting(最小费用最大流)
生活随笔
收集整理的這篇文章主要介紹了
SCU3033 Destroying a Painting(最小费用最大流)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目大概說有一個有n*m個格子的畫板,畫板上每個格子都有顏色,現在要把所有格子的顏色改成紅、綠或者藍,改變的代價是二者RGB值的曼哈頓距離,還要求紅綠藍格子個數的最大值和最小值要盡可能接近,問最少的代價是多少。
紅綠藍三色的個數是可以直接確定的,分別考慮幾個情況就OK了,然后就是根據紅綠藍的個數構圖跑最小費用最大流。。
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<algorithm> 5 using namespace std; 6 #define INF (1<<30) 7 #define MAXN 444 8 #define MAXM 444*888 9 struct Edge{ 10 int u,v,cap,cost,next; 11 }edge[MAXM]; 12 int head[MAXN]; 13 int NV,NE,vs,vt; 14 15 void addEdge(int u,int v,int cap,int cost){ 16 edge[NE].u=u; edge[NE].v=v; edge[NE].cap=cap; edge[NE].cost=cost; 17 edge[NE].next=head[u]; head[u]=NE++; 18 edge[NE].u=v; edge[NE].v=u; edge[NE].cap=0; edge[NE].cost=-cost; 19 edge[NE].next=head[v]; head[v]=NE++; 20 } 21 bool vis[MAXN]; 22 int d[MAXN],pre[MAXN]; 23 bool SPFA(){ 24 for(int i=0;i<NV;++i){ 25 vis[i]=0; 26 d[i]=INF; 27 } 28 vis[vs]=1; 29 d[vs]=0; 30 queue<int> que; 31 que.push(vs); 32 while(!que.empty()){ 33 int u=que.front(); que.pop(); 34 for(int i=head[u]; i!=-1; i=edge[i].next){ 35 int v=edge[i].v; 36 if(edge[i].cap && d[v]>d[u]+edge[i].cost){ 37 d[v]=d[u]+edge[i].cost; 38 pre[v]=i; 39 if(!vis[v]){ 40 vis[v]=1; 41 que.push(v); 42 } 43 } 44 } 45 vis[u]=0; 46 } 47 return d[vt]!=INF; 48 } 49 int MCMF(){ 50 int res=0; 51 while(SPFA()){ 52 int flow=INF,cost=0; 53 for(int u=vt; u!=vs; u=edge[pre[u]].u){ 54 flow=min(flow,edge[pre[u]].cap); 55 } 56 for(int u=vt; u!=vs; u=edge[pre[u]].u){ 57 edge[pre[u]].cap-=flow; 58 edge[pre[u]^1].cap+=flow; 59 cost+=flow*edge[pre[u]].cost; 60 } 61 res+=cost; 62 } 63 return res; 64 } 65 66 inline void in(int &ret){ 67 char c; ret=0; 68 while(c=getchar(),c<'0'||c>'9'); 69 while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar(); 70 } 71 int n,m,R[22][22],G[22][22],B[22][22]; 72 int get(int r,int g,int b){ 73 vs=n*m+3; vt=vs+1; NV=vt+1; NE=0; 74 memset(head,-1,sizeof(head)); 75 addEdge(n*m,vt,r,0); 76 addEdge(n*m+1,vt,g,0); 77 addEdge(n*m+2,vt,b,0); 78 for(int i=0; i<n; ++i){ 79 for(int j=0; j<m; ++j){ 80 addEdge(vs,i*m+j,1,0); 81 addEdge(i*m+j,n*m,1,abs(255-R[i][j])+G[i][j]+B[i][j]); 82 addEdge(i*m+j,n*m+1,1,R[i][j]+abs(255-G[i][j])+B[i][j]); 83 addEdge(i*m+j,n*m+2,1,R[i][j]+G[i][j]+abs(255-B[i][j])); 84 } 85 } 86 return MCMF(); 87 } 88 int main(){ 89 int t; 90 in(t); 91 for(int cse=1; cse<=t; ++cse){ 92 in(n); in(m); 93 for(int i=0; i<n; ++i){ 94 for(int j=0; j<m; ++j){ 95 in(R[i][j]); in(G[i][j]); in(B[i][j]); 96 } 97 } 98 int ans=INF; 99 if(n*m%3==0){ 100 ans=min(ans,get(n*m/3,n*m/3,n*m/3)); 101 }else if(n*m%3==1){ 102 ans=min(ans,get(n*m/3+1,n*m/3,n*m/3)); 103 ans=min(ans,get(n*m/3,n*m/3+1,n*m/3)); 104 ans=min(ans,get(n*m/3,n*m/3,n*m/3+1)); 105 }else{ 106 ans=min(ans,get(n*m/3+1,n*m/3+1,n*m/3)); 107 ans=min(ans,get(n*m/3+1,n*m/3,n*m/3+1)); 108 ans=min(ans,get(n*m/3,n*m/3+1,n*m/3+1)); 109 } 110 printf("Case %d: %d\n",cse,ans); 111 } 112 return 0; 113 }?
轉載于:https://www.cnblogs.com/WABoss/p/5364266.html
總結
以上是生活随笔為你收集整理的SCU3033 Destroying a Painting(最小费用最大流)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【C语言重点难点精讲】C语言文件
- 下一篇: [linux]unixODBC的安装配置