您的位置:首页 > 大数据 > 人工智能

SCU3033 Destroying a Painting(最小费用最大流)

2016-04-07 16:46 555 查看
题目大概说有一个有n*m个格子的画板,画板上每个格子都有颜色,现在要把所有格子的颜色改成红、绿或者蓝,改变的代价是二者RGB值的曼哈顿距离,还要求红绿蓝格子个数的最大值和最小值要尽可能接近,问最少的代价是多少。

红绿蓝三色的个数是可以直接确定的,分别考虑几个情况就OK了,然后就是根据红绿蓝的个数构图跑最小费用最大流。。

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define INF (1<<30)
#define MAXN 444
#define MAXM 444*888
struct Edge{
int u,v,cap,cost,next;
}edge[MAXM];
int head[MAXN];
int NV,NE,vs,vt;

void addEdge(int u,int v,int cap,int cost){
edge[NE].u=u; edge[NE].v=v; edge[NE].cap=cap; edge[NE].cost=cost;
edge[NE].next=head[u]; head[u]=NE++;
edge[NE].u=v; edge[NE].v=u; edge[NE].cap=0; edge[NE].cost=-cost;
edge[NE].next=head[v]; head[v]=NE++;
}
bool vis[MAXN];
int d[MAXN],pre[MAXN];
bool SPFA(){
for(int i=0;i<NV;++i){
vis[i]=0;
d[i]=INF;
}
vis[vs]=1;
d[vs]=0;
queue<int> que;
que.push(vs);
while(!que.empty()){
int u=que.front(); que.pop();
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap && d[v]>d[u]+edge[i].cost){
d[v]=d[u]+edge[i].cost;
pre[v]=i;
if(!vis[v]){
vis[v]=1;
que.push(v);
}
}
}
vis[u]=0;
}
return d[vt]!=INF;
}
int MCMF(){
int res=0;
while(SPFA()){
int flow=INF,cost=0;
for(int u=vt; u!=vs; u=edge[pre[u]].u){
flow=min(flow,edge[pre[u]].cap);
}
for(int u=vt; u!=vs; u=edge[pre[u]].u){
edge[pre[u]].cap-=flow;
edge[pre[u]^1].cap+=flow;
cost+=flow*edge[pre[u]].cost;
}
res+=cost;
}
return res;
}

inline void in(int &ret){
char c; ret=0;
while(c=getchar(),c<'0'||c>'9');
while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
}
int n,m,R[22][22],G[22][22],B[22][22];
int get(int r,int g,int b){
vs=n*m+3; vt=vs+1; NV=vt+1; NE=0;
memset(head,-1,sizeof(head));
addEdge(n*m,vt,r,0);
addEdge(n*m+1,vt,g,0);
addEdge(n*m+2,vt,b,0);
for(int i=0; i<n; ++i){
for(int j=0; j<m; ++j){
addEdge(vs,i*m+j,1,0);
addEdge(i*m+j,n*m,1,abs(255-R[i][j])+G[i][j]+B[i][j]);
addEdge(i*m+j,n*m+1,1,R[i][j]+abs(255-G[i][j])+B[i][j]);
addEdge(i*m+j,n*m+2,1,R[i][j]+G[i][j]+abs(255-B[i][j]));
}
}
return MCMF();
}
int main(){
int t;
in(t);
for(int cse=1; cse<=t; ++cse){
in(n); in(m);
for(int i=0; i<n; ++i){
for(int j=0; j<m; ++j){
in(R[i][j]); in(G[i][j]); in(B[i][j]);
}
}
int ans=INF;
if(n*m%3==0){
ans=min(ans,get(n*m/3,n*m/3,n*m/3));
}else if(n*m%3==1){
ans=min(ans,get(n*m/3+1,n*m/3,n*m/3));
ans=min(ans,get(n*m/3,n*m/3+1,n*m/3));
ans=min(ans,get(n*m/3,n*m/3,n*m/3+1));
}else{
ans=min(ans,get(n*m/3+1,n*m/3+1,n*m/3));
ans=min(ans,get(n*m/3+1,n*m/3,n*m/3+1));
ans=min(ans,get(n*m/3,n*m/3+1,n*m/3+1));
}
printf("Case %d: %d\n",cse,ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: