http://www.sdutacm.org/sdutoj/showproblem.php?pid=2414&cid=1744
最小费用最大流,开始ps用贪心,每次找出最大高度或者最小高度的插入,然后如果最大高度的能插入则插最大的,否则就插小的,(注意插入时候需要贪心两步)感觉是可以的,但是最终问题出在哪里好像还不知道。
一个不错的网址:http://www.hardbird.net/%E5%B1%B1%E4%B8%9C%E7%9C%81%E7%AC%AC%E4%B8%89%E5%B1%8A%E7%9C%81%E8%B5%9B-c-%E9%A2%98-an-interesting-game%E8%B4%B9%E7%94%A8%E6%B5%81/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int maxn=2200;
const int oo=0x3f3f3f3f;
struct Edge
{
int u, v, cap, flow, cost;Edge(){}
Edge(int u, int v, int cap, int flow, int cost):u(u), v(v), cap(cap), flow(flow), cost(cost) {}
};
struct MCMF
{
int n, m, s, t;
vector<Edge> edge;
vector<int> G[maxn];
int inq[maxn], d[maxn], p[maxn], a[maxn];
void init(int n)
{
this->n=n;
for(int i=0; i<n; i++)
G[i].clear();
edge.clear();
}
void AddEdge(int u, int v, int cap, int cost)
{
edge.push_back(Edge(u, v, cap, 0, cost));
edge.push_back(Edge(v, u, 0, 0, -cost));
m=edge.size();
G[u].push_back(m-2);
G[v].push_back(m-1);
}
bool spfa(int s, int t, int& flow, int& cost)
{
memset(d, 0x3f, sizeof d);
memset(inq, 0, sizeof inq);
d[s]=0, inq[s]=1, p[s]=0, a[s]=oo;
queue<int> q;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
inq[u]=0;
for(int i=0; i<G[u].size(); i++)
{
Edge& e=edge[G[u][i]];
if(e.cap>e.flow && d[e.v]>d[u]+e.cost)
{
d[e.v]=d[u]+e.cost;
p[e.v]=G[u][i];
a[e.v]=min(a[u], e.cap-e.flow);
if(!inq[e.v])
{
q.push(e.v);
inq[e.v]=1;
}
}
}
}
if(d[t]==oo)return false;
flow+=a[t];
cost+=d[t]*a[t];
int u=t;
while(u!=s)
{
edge[p[u]].flow+=a[t];
edge[p[u]^1].flow-=a[t];
u=edge[p[u]].u;
}
return true;
}
int MinCost(int s, int t)
{
int flow=0, cost=0;
while(spfa(s, t, flow, cost));
return cost;
}
} net;
int a[maxn], b[maxn];
int main()
{
int T, kase=0;
scanf("%d", &T);
while(T--)
{
int n, m, k, ans=0;
scanf("%d%d%d", &n, &m, &k);
net.init(n+100);
memset(b, 0, sizeof b);
for(int i=0; i<n; i++)
scanf("%d", a+i);
for(int i=0; i<m; i++)
{
int x;
scanf("%d", &x);
b[x]++;
}
for(int i=1; i<n; i++)
{
ans+=abs(a[i]-a[i-1]);
net.AddEdge(0, i, 1, 0);
for(int j=0; j<=30; j++)
if(b[j])
{
int dis=abs(a[i]-j)+abs(a[i-1]-j)-abs(a[i]-a[i-1]);
net.AddEdge(i, n+j, 1, -dis);
}
}
int S=n+50, T=S+1;
for(int i=0; i<=30; i++)
if(b[i])
net.AddEdge(i+n, T, b[i], 0);
net.AddEdge(S, 0, k, 0);
printf("Case %d: %d\n", ++kase, ans-net.MinCost(S, T));
}
return 0;
}
浙公网安备 33010602011771号