【SDUT2414】An interesting game——最小费用

来源:互联网 发布:unity3d arduino 编辑:程序博客网 时间:2024/05/24 16:15

题目描述
Xiao Ming recently designs a little game, in front of player there are N small hillsides put in order, now Xiao Ming wants to increase some hillsides to block the player, so he prepared another M hillsides, but he does not hope it will be too difficult,so only K in M hillsides are selected to add at most. Paying attention to the original N hillsides, between each two can add only one hillside. Xiao Ming expects players from the starting place to reach the destination in turn and passes all the hillsides to make his distance travelled longest. Please help Xiao Ming how to add the hillsides that he prepared. Note: The distance between two hillsides is the absolute value of their height difference.

输入
The first line of input is T, (1 <= T <= 100) the number of test cases. Each test case starts with three integers N,M,K (2 <= N <= 1000, 1 <= M <= 1000, 1 <= K <= M and 1 <= K < N), which means that the number of original hillsides, the number of hillsides Xiao Ming prepared and The number of most Xiao Ming can choose from he prepared. Then follow two lines, the first line contains N integers Xi (0 <= Xi <= 30), denoting the height of each original hillside, Note: The first integer is player’s starting place and the last integer is player’s destination. The second line contains M integers Yi (0 <= Yi <= 30), denoting the height of prepared each hillsides.

输出
For every test case, you should output “Case k: ” first in a single line, where k indicates the case number and starts from 1. Then print the distance player can travel longest.

示例输入
3
2 1 1
6 9
8
2 1 1
6 9
15
3 2 1
5 9 15
21 22
示例输出
Case 1: 3
Case 2: 15
Case 3: 36
提示

来源
2012年”浪潮杯”山东省第三届ACM大学生程序设计竞赛

开始的时候以为是贪心,ZX按照思路敲出来WA了,赛后看到题解是最小费用,自己还是太年轻

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <queue>#include <algorithm>using namespace std;const int INF = 0x3f3f3f3f;const int Max = 1100;typedef struct node{    int v,cap,flow,cost,next;}edge;edge e[Max*500];int H[Max],top;int dis[Max];bool vis[Max];int pre[Max];int s,t;int a[Max];int b[50];void AddEdge(int u,int v,int cap,int cost)//建图{    e[top].v = v; e[top].cap = cap; e[top].cost = cost;    e[top].next = H[u] ; H[u] = top++;    e[top].v = u; e[top].cap = 0; e[top].cost = -cost;    e[top].next = H[v] ; H[v] = top++;}bool SPFA()//最短路找增广路{    queue<int>Q;    memset(dis,INF,sizeof(dis));    memset(vis,false,sizeof(vis));    memset(pre,-1,sizeof(pre));    vis[s] = true;    dis[s] = 0;    Q.push(s);    while(!Q.empty())    {        int u = Q.front();        Q.pop();        for(int i = H[u];~i;i = e[i].next)        {            if(e[i].cap>0&&dis[e[i].v]>dis[u]+e[i].cost)            {                pre[e[i].v] = i;                dis[e[i].v] = dis[u]+e[i].cost;                if(!vis[e[i].v])                {                    vis[e[i].v] = true;                    Q.push(e[i].v);                }            }        }        vis[u] = false;    }    return dis[t]!=INF;}int argument()//增广{    int ans = INF,ant = 0;    for(int i = t;i!=s;i = e[pre[i]^1].v)    {        e[pre[i]].cap-=1;        e[pre[i]^1].cap+=1;        ant +=e[pre[i]].cost;    }    return ant;}int MinCost()//求最小费用{    int ans = 0;    while(SPFA())    {        ans+=argument();    }    return ans;}int main(){    int n,m,k,T,data;    int z = 1;    scanf("%d",&T);    while(T--)    {        scanf("%d %d %d",&n,&m,&k);        memset(b,0,sizeof(b));        for(int i = 1;i<=n;i++)        {            scanf("%d",&a[i]);        }        for(int i = 1;i<=m;i++)        {            scanf("%d",&data);            b[data]++;        }        int ans = 0;        memset(H,-1,sizeof(H));        top = 0;        s = 0,t = n+50;        for(int i = 1;i<n;i++)        {            ans+=abs(a[i]-a[i+1]);            AddEdge(s,i,1,0);            for(int j = 0;j<=30;j++)            {                if(b[j])                {                    data = abs(a[i]-j)+abs(a[i+1]-j)-abs(a[i]-a[i+1]);                    AddEdge(i,n+j,1,-data);                }            }        }        for(int i = 0;i<=30;i++)        {            if(b[i]) AddEdge(n+i,t-1,b[i],0);        }        AddEdge(t-1,t,k,0);        printf("Case %d: %d\n",z++,ans-MinCost());    }    return 0;}
0 0