ZOJ_2710_ Two Pipelines(贪心)

本文探讨了如何在确保两根石油管道连接城市数量接近的前提下,使运输成本最小化的算法实现。通过计算几何和贪心策略确定各城市应连接哪根管道,并调整以满足数量限制。

Two Pipelines
Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu

Description

There are two oil pipelines going through Flatland. Each pipeline can be considered as a line on the plane.

Recently the president of Flatland has decided to bring oil to all n cities of Flatland. Therefore he would like to build pipes from each city to one of the pipelines. The minister of industry and education has provided him with data about demand for oil in each city. Transporting a barrel of oil for one kilometer costs 1 flatlar.

The president ordered to connect each city to the closest pipleine, but it turned out that there is one problem. One pipeline belongs to a strong Hrundi Empire, while the other belongs to Bordland Republic. Since president wants to keep good relationships with both countries, he must not give preference to one of the pipelines. That is, if there would be x cities connected to one pipeline and y cities connected to the other, |x - y| must not exceed c .

Help president to decide which city should be connected to which pipeline, so that he keeps his international reputation clean, and spends as few money as possible.

Input

There are mutiple cases in the input file.

The first line of the input file contains n and c (1 <= c <= n <= 200 ). The second line contains the description of the first pipeline --- coordinates of two different points that are lying on it: x1 , y1 , x2 , y2 . The third line describes the second pipeline in the same format.

The following n lines describe cities. Each city is described with three integer numbers: its coordinates and the demand for the oil in thousands of barrels per day (it does not exceed 1000 ).

All coordinates are integer, given in kilometers and do not exceed 104 by absolute values. No two cities coincide. Pipelines do not coincide either.

There is an empty line after each case.

Output

For each city output 1 if it must be connected to the first pipeline, or 2 if it must be connected to the second pipeline.

There should be am empty line after each case.

Sample Input

3 1
0 0 10 0
0 5 7 5
-2 1 1
1 1 1
4 2 10

Sample Output

1 2 1


题型:计算几何、贪心


题意:

         用两根管道对n个城市输送石油,运送石油的成本每桶每公里为1,设有x个城市在第一根管子上,y个城市在第二根管子上,要求在保证|x-y| <= c的情况下使得成本尽可能的低,顺序输出城市所在的管道。

第一行输入n和c,接下来两行分别输入第一根管道上的两个点的坐标和第二根管道上两个点的坐标,再接下来n行输入每个城市的坐标及该城市每天所需要的油量。


分析:

         首先需要注意管子是直线而不是线段。

         先不考虑按|x-y| <= c来分配城市,那么最优解就是这个城市离那个管子近就把它分配到哪个管子,这样的话就化为求点到直线距离的问题了,用贪心的思想,这个点离一管近就安在一管上,离二管近就安在二管上,之后就可以将所有的城市分为了两个部分;然后,当分出来的结果不满足|x-y| <= c时,就需要从城市数多的管子上取出一部分城市安在另一根管子上,为了保证最终的成本尽可能低,可以先计算出每个点到一管花的钱与到二管花的钱的差值的绝对值,将差值sort一下,然后将差值小的安在另一根管子上,这样就能保证最终的成本是最低的了。

         用结构体来表示这些城市,要把点安到另一根管子上只有把choice改一下就行了。。。


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
struct point{
    int x,y,need,choice;//坐标、需要的油量、选择安的管子
    double h1,h2;//到一管的距离,到二管的距离
};//表示城市

struct tmp{
    int num;
    double cost;//到一管和到二管的成本的差值的绝对值
};

point p[250];
tmp t[250];

double caldis(double x1,double y1,double x2,double y2){//求两点距离
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}

double area(double x0,double y0,double x1,double y1,double x2,double y2){//求三角形面积
    return fabs(x0*y1+x2*y0+x1*y2-x2*y1-x0*y2-x1*y0);
}

double calhigh(double x,double y,double ax,double ay,double bx,double by){//求高得出点到直线距离
    return (area(x,y,ax,ay,bx,by)/caldis(ax,ay,bx,by));
}

double cmp(tmp a,tmp b){
    if(a.cost==b.cost){
        return a.num<b.num;
    }
    else{
        return a.cost<b.cost;
    }

}

int main(){
    int n,c;
    int ax,ay,bx,by,cx,cy,dx,dy;//一管和二管上的两个点
    int cnt1,cnt2;
    while(~scanf("%d%d",&n,&c)){
        cnt1=cnt2=0;
        scanf("%d%d%d%d",&ax,&ay,&bx,&by);
        scanf("%d%d%d%d",&cx,&cy,&dx,&dy);
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].need);
            p[i].h1=calhigh(p[i].x,p[i].y,ax,ay,bx,by);
            p[i].h2=calhigh(p[i].x,p[i].y,cx,cy,dx,dy);
            if(p[i].h1<p[i].h2){
                p[i].choice=1;
                cnt1++;
            }
            else{
                p[i].choice=2;
                cnt2++;
            }
        }

        if(abs(cnt1-cnt2)>c){
            for(int i=1;i<=n;i++){
                t[i].num=i;
                t[i].cost=fabs(p[i].h1-p[i].h2)*p[i].need;
            }
            sort(t+1,t+n+1,cmp);
            if(cnt1>cnt2){
                for(int i=1;i<=n;i++){
                    if(p[t[i].num].choice==1){
                        p[t[i].num].choice=2;
                        cnt1--;
                        cnt2++;
                        if(cnt1-cnt2<=c){
                            break;
                        }
                    }
                }
            }
            else if(cnt1<cnt2){
                for(int i=1;i<=n;i++){
                    if(p[t[i].num].choice==2){
                        p[t[i].num].choice=1;
                        cnt2--;
                        cnt1++;
                        if(cnt2-cnt1<=c){
                            break;
                        }
                    }
                }
            }
        }

        for(int i=1;i<n;i++){
            printf("%d ",p[i].choice);
        }
        printf("%d\n\n",p[n].choice);
    }
    return 0;
}




内容概要:本文介绍了一个针对电力系统连锁故障传播路径的N-k多阶段双层优化及故障场景筛选模型,该模型基于混合整数线性规划(MILP)方法构建,旨在全面评估电力系统在遭受多重故障时的脆弱性与恢复能力。通过引入故障传播路径的概念,模型能够动态模拟故障在电网中的逐级扩散过程,并结合多阶段优化策略,实现对关键故障场景的有效识别与优先排序。整个框架不仅考虑了初始故障元件的选取,还涵盖了后续因潮流转移引发的级联跳闸行为,从而提升了风险评估的准确性与时效性。该研究已在Matlab平台上完成代码实现,具备良好的可复现性和工程应用价值,适用于提升现代电网的安全防御水平。; 适合人群:电力系统、能源安全及相关领域的科研人员、高校研究生以及从事电网规划与运行管理的工程技术人员。; 使用场景及目标:①用于电力系统安全评估中识别最危险的N-k故障组合;②支撑电网应急预案制定与薄弱环节改造;③作为学术研究中关于级联故障建模与优化求解的教学与验证工具;④服务于智能电网背景下抵御蓄意攻击或极端事件的风险防控决策。; 阅读建议:建议读者结合Matlab代码深入理解模型的数学 formulation 与求解流程,重点关注目标函数设计、约束条件构建及双层优化结构的实现逻辑,同时可通过调整系统参数和故障设定进行仿真对比分析,以掌握不同因素对连锁故障演化的影响规律。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值