• CodeChef


    题目链接

    SPCLN: 太空清扫 题目描述

    一架宇宙飞船准备要穿过一条长长的星际隧道。隧道由 N 个静止的太空碎片组成。为了成功 地完成任务,飞船需要摧毁所有太空碎片。飞船的控制单元由 M 个按钮组成,这些按钮可以被用 来摧毁太空碎片。按下某个特定的按钮可能造成某些(也许多个)太空碎片被摧毁。一旦一个太 空碎片被摧毁,其质量将被转换成能量,这些能量将最终被飞船所吸收以提高其速度。一个特定 碎片被摧毁所释放的能量与被用来摧毁它的按钮有关。我们定义一个能量矩阵 E,对于每个碎片 i 和按钮 j,E[i][j](0 ≤ E[i][j] ≤ 100) 表示用按钮 j 摧毁碎片 i 所释放的能量。若 E[i][j] = −1 表 示碎片 i 不能被按钮 j 摧毁。

    一些碎片的摧毁有依赖关系。飞船必须在摧毁某些碎片前先将另一些碎片摧毁。这里一共有 K 组依赖关系。每组依赖关系包含两个用空格隔开的整数 i 和 j,表示碎片 i 的摧毁必须发生在碎 片 j 的摧毁之前。

    每一个按钮只能被按下一次,而且必须按照 1 ∼ M 的顺序按下(如按钮 2 不能在按钮 1 前被 按下)。当按下一个按钮时,我们定义“目标向量”为一个长为 N 的二进制字符串 T 。对于碎片 i,若 T [i] 为 1,表示你希望用这个按钮去摧毁碎片 i,否则 T [i] 为 0。当按钮被按下时,所有在目 标向量中出现过的碎片将同时被摧毁。

    飞船可以用某个按钮摧毁任意数量的碎片,包括 0 个,只要它们能被这个按钮摧毁,并满足 依赖关系。

      现在你的任务是计算飞船通过这条隧道所能获得的最大平均能量。
    

    输入格式

    输入第一行包括两个用空格隔开的整数 N 和 M。
    接下来 N 行,每行 M 个整数,表示 E[i][j]。
    接下来一行包含一个整数 K。
    接下来 K 行,每行包含两个用空格隔开的整数 u 和 v(u ̸= v),表示碎片 u 必须在碎片 v 前

    被摧毁。

    输出格式

      输出一个实数表示最大平均能量,请四舍五入保留小数点后两位。
    

    数据范围与约定

    • 1 ≤ M, N ≤ 100
    • 0≤K≤100
    • −1≤E[i][j]≤100
    • 1≤u,v≤N
    • 数据保证存在摧毁所有碎片的方案。

    样例数据

    输入

    3 3
    10 70 100 

    80 50 40

    80 20 40

    2
    1 2

    1 3

    输出

    50.00

    样例解释

      唯一的摧毁所有碎片的方案为:用第二个按钮摧毁第一个碎片,用第三个按钮摧毁第二个和
    第三个碎片。
    

    平均能量为 (70 + 40 + 40)/3 = 50.00。 

    题解:这题问了qls才知道怎么做的。

    因为题目说了要摧毁所有的碎片,所以就是最大化能量总和。

    这样建图:对于每个碎片拆成m+1个点,第i个碎片的第j个点向第j+1个点连一条100-E[i][j]的边,对于k个限制条件,如果碎片u要在碎片v之前被摧毁,那么碎片u的第j个点向第j+1个点连容量为inf的边,然后源点s向每个碎片的第一个点连一条容量为inf的边,每个碎片的最后一点向汇端t连一条容量为inf的边,然后跑一遍s-t的最小割,记最小割为ans,用(100*n-ans)/n即为答案

    神建图!

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<stack>
    using namespace std;
    #define rep(i,a,n) for (int i=a;i<n;i++)
    #define per(i,a,n) for (int i=n-1;i>=a;i--)
    #define pb push_back
    #define fi first
    #define se second
    typedef vector<int> VI;
    typedef long long ll;
    typedef pair<int,int> PII;
    const int inf=0x3fffffff;
    const ll mod=1000000007;
    const int maxn=11000;
    const int maxm=100500;
    struct Node
    {
        int from,to,next;
        int cap;
    }edge[maxm];
    int tol;
    int dep[maxn];
    int head[maxn];
    void init()
    {
        tol=0;
        memset(head,-1,sizeof(head));
    }
    void addedge(int u,int v,int w)//第一条边下标必须为偶数
    {
        edge[tol].from=u;edge[tol].to=v;edge[tol].cap=w;edge[tol].next=head[u];head[u]=tol++;
        edge[tol].from=v;edge[tol].to=u;edge[tol].cap=0;edge[tol].next=head[v];head[v]=tol++;
    }
    int BFS(int start,int end)
    {
        int que[maxn];
        int front,rear;
        front=rear=0;
        memset(dep,-1,sizeof(dep));
        que[rear++]=start;
        dep[start]=0;
        while(front!=rear)
        {
            int u=que[front++];
            if(front==maxn)front=0;
            for(int i=head[u];i!=-1;i=edge[i].next)
            {
                int v=edge[i].to;
                if(edge[i].cap>0&&dep[v]==-1)
                {
                    dep[v]=dep[u]+1;
                    que[rear++]=v;
                    if(rear>=maxn)rear=0;
                    if(v==end)return 1;
                }
            }
        }
        return 0;
    }
    int a[110][110];
    int dinic(int start,int end)
    {
        int res=0;
        int top;
        int stack[maxn];
        int cur[maxn];
        while(BFS(start,end))
        {
            memcpy(cur,head,sizeof(head));
            int u=start;
            top=0;
            while(1)
            {
                if(u==end)
                {
                    int min=inf;
                    int loc;
                    for(int i=0;i<top;i++)
                        if(min>edge[stack[i]].cap)
                        {
                            min=edge[stack[i]].cap;
                            loc=i;
                        }
                    for(int i=0;i<top;i++)
                    {
                        edge[stack[i]].cap-=min;
                        edge[stack[i]^1].cap+=min;
                    }
                    res+=min;
                    top=loc;
                    u=edge[stack[top]].from;
                }
                for(int i=cur[u];i!=-1;cur[u]=i=edge[i].next)
                    if(edge[i].cap!=0&&dep[u]+1==dep[edge[i].to])
                        break;
                if(cur[u]!=-1)
                {
                    stack[top++]=cur[u];
                    u=edge[cur[u]].to;
                }
                else
                {
                    if(top==0)break;
                    dep[u]=-1;
                    u=edge[stack[--top]].from;
                }
            }
        }
        return res;
    }
    int main()
    {
        int n,m,k;
        scanf("%d%d",&n,&m);
        init();
        int st=0,ed=n*(m+1)+1;
        rep(i,1,n+1) rep(j,1,m+1) scanf("%d",&a[i][j]);
        rep(i,1,n+1) rep(j,1,m+1) addedge((m+1)*(i-1)+j,(m+1)*(i-1)+j+1,100-a[i][j]);
        rep(i,1,n+1) addedge(st,(i-1)*(m+1)+1,inf),addedge(i*(m+1),ed,inf);
        scanf("%d",&k);
        rep(i,1,k+1)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            rep(j,1,m+1)
                addedge((u-1)*(m+1)+j,(v-1)*(m+1)+j+1,inf);
        }
        printf("%.2lf
    ",1.0*(100*n-dinic(st,ed))/n);
        return 0;
    }
  • 相关阅读:
    百分点零售行业大数据解决方案
    百分点用户标签管理系统
    百分点个性化系统解决方案
    百分点数据洞察系统解决方案
    来学学数据分析吧(二)第一章 预测和关联数量特征
    来学学数据分析吧(一)
    生产者和消费者问题学习以及Java实现
    java中的双重锁定检查(Double Check Lock)
    python学习(十四)面向对象
    python学习(十二)模块
  • 原文地址:https://www.cnblogs.com/tarjan/p/7258407.html
Copyright © 2020-2023  润新知