Codeforces_GYM Flight Boarding Optimization

本文介绍了一种通过划分登机区域来最小化乘客登机难度的方法。利用动态规划结合四边形优化技巧,实现了高效的算法设计。同时给出了线段树优化和正解代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(ACM ICPC 2013–2014, NEERC, Northern Subregional Contest)

Flight Boarding Optimization
Input file: flight.in
Output file: flight.out
Time limit: 2 seconds
Memory limit: 256 megabytes
Peter is an executive boarding manager in Byteland airport. His job is to optimize the boarding process.
The planes in Byteland have s rows, numbered from 1 to s. Every row has six seats, labeled A to F.
There are n passengers, they form a queue and board the plane one by one. If the i-th passenger sits in
a row r i then the difficulty of boarding for him is equal to the number of passengers boarded before him
and sit in rows 1...r i −1. The total difficulty of the boarding is the sum of difficulties for all passengers.
For example, if there are ten passengers, and their seats are 6A, 4B, 2E, 5F, 2A, 3F, 1C, 10E, 8B, 5A,
in the queue order, then the difficulties of their boarding are 0, 0, 0, 2, 0, 2, 0, 7, 7, 5, and the total
difficulty is 23.
To optimize the boarding, Peter wants to divide the plane into k zones. Every zone must be a continuous
range of rows. Than the boarding process is performed in k phases. On every phase, one zone is selected
and passengers whose seats are in this zone are boarding in the order they were in the initial queue.
In the example above, if we divide the plane into two zones: rows 5–10 and rows 1–4, then during the first
phase the passengers will take seats 6A, 5F, 10E, 8B, 5A, and during the second phase the passengers
will take seats 4B, 2E, 2A, 3F, 1C, in this order. The total difficulty of the boarding will be 6.
Help Peter to find the division of the plane into k zones which minimizes the total difficulty of the
boarding, given a specific queue of passengers.
Input
The first line contains three integers n (1 ≤ n ≤ 1000), s (1 ≤ s ≤ 1000), and k (1 ≤ k ≤ 50; k ≤ s).
The next line contains n integers r i (1 ≤ r i ≤ s).
Each row is occupied by at most 6 passengers.
Output
Output one number, the minimal possible difficulty of the boarding.
Example
flight.in                             flight.out
10 12 2                            6
6 4 2 5 2 3 1 11 8 5

 

此题做的倒是一波三折,

  f[i][j]=min(f[k][j-1]+w[k+1][i])

起先w[][]不会算,凭借wlm牛给的线段树思路起家,之后我调试代码,思路中断,混淆,最终还是wlm牛成功计算出了w[][]

然而在我的kn^2的朴素思想下,过了样例,草草上交,”in Queue“,CF跪了,草!

不管其他,以防万一,匆匆把代码改成了四边形优化,O(nk),其实很像poj1160,只是为了防止超时。

靠!WA on test 5!!! 最后一刻看朴素提交竟然WA了,而四边形优化还在 in Queue,目测裸算法跪了,加优化又能如何?

 

吃饭,回新校区,一路上和这群acm伙伴各种hi,别是高兴啊。

挖槽!打开电脑时(笔记本已断网),发现四边形优化 Run on test 40,惊呆了。

马上联网一看,A了,吐血啊!!~~~~~~~————————****¥¥¥%%%####

 

第二天又看了别人代码,也明白了正解。

 

题目大意:

  乘客按顺序进客机,每进来一个乘客会产生不满度(difficulty),是他之前进来的且坐在他前面的乘客人数,现在可以分k个机厢,求最少difficulty

思路:

  f[i][j]=min(f[k][j-1]+w[k+1][i])

  w[][]求法巧妙,看正解代码即可知晓。

 

以下给出 

 

线段树+四边形优化代码 O(n^2logn+nk)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <utility>
#include <stack>
#include <queue>
#include <map>
#include <deque>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define INF 0x3f3f3f3f
#define N 1005

using namespace std;
struct Point
{
    int r,res;
}a[N];

int w[N][N],n,s,k,sum[N*N],f[N][N],ss[N][N];
bool isCalc[N];

bool cmp(Point a, Point b)
{
    if(a.r==b.r)
        return a.res>b.res;
    return a.r<b.r;
}

void PushUp(int rt){
    sum[rt]=sum[rt*2]+sum[rt*2+1];
}
void build(int l, int r, int rt)
{
    sum[rt]=0;
    if(l==r) return;
    int m=(l+r)/2;
    build(l,m,rt*2);
    build(m+1,r,rt*2+1);
}
void update(int x, int l, int r, int rt)
{
    if(l==r) 
    {
        sum[rt]=1;
        return;
    }
    int m=(l+r)/2;
    if(x<=m) update(x,l,m,rt*2);
    else update(x,m+1,r,rt*2+1);
    PushUp(rt);
}
int query(int x, int y, int l, int r, int rt)
{
    if(x>y) return 0;
    if(x<=l&&y>=r) return sum[rt];
    int m=(l+r)/2;
    int s=0;
    if(x<=m) s+=query(x,y,l,m,rt*2);
    if(y>m) s+=query(x,y,m+1,r,rt*2+1);
    return s;
}
int main()
{
    // freopen("flight.in","r",stdin);
    // freopen("flight.out","w",stdout);
    scanf("%d%d%d",&n,&s,&k);
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&a[i].r);
        a[i].res=i;
    }
    sort(a+1,a+n+1,cmp);
    int head=1,d=1;
    for(int i=1; i<=s; i++)
    {
        build(1,n,1);
        memset(isCalc,0,sizeof(isCalc));
        d=i;
        int tmp=0;
        while(a[head].r<i) head++;
        for(int j=head; j<=n; j++)
        {
            update(a[j].res,1,n,1);
            while(d<a[j].r)
            {
                if(!isCalc[d])
                {
                    w[i][d]=tmp;
                }
                d++;
            }
            tmp+=query(1,a[j].res-1,1,n,1);
            w[i][a[j].r]=tmp;
            isCalc[a[j].r]=1;
        }
        while(d<=s)
        {
            if(!isCalc[d])
            {
                w[i][d]=w[i][d-1];
            }
            d++;
        }
    }
    for(int i=0; i<=s; i++)
        for(int j=0; j<=k; j++)
        f[i][j]=INF;
    for(int i=1; i<=s; i++)
        f[i][1]=w[1][i];

    for(int j=2; j<=k; j++)
    {
        ss[s+1][j]=s-1;
        for(int i=s; i>=j; i--)
        {
            for(int l=ss[i][j-1]; l<=ss[i+1][j]; l++)
            if(f[i][j]>f[l][j-1]+w[l+1][i])
            {
                f[i][j]=f[l][j-1]+w[l+1][i];
                ss[i][j]=l;
            }
        }
    }
    printf("%d",f[s][k]);
    return 0;
}
View Code

 

线段树+朴素代码O(n^2logn+kn^2)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <utility>
#include <stack>
#include <queue>
#include <map>
#include <deque>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define INF 0x3f3f3f3f
#define N 1005

using namespace std;
struct Point
{
    int r,res;
}a[N];

int w[N][N],n,s,k,sum[N*N],f[N][N];
bool isCalc[N];

bool cmp(Point a, Point b)
{
    if(a.r==b.r)
        return a.res>b.res;
    return a.r<b.r;
}

void PushUp(int rt){
    sum[rt]=sum[rt*2]+sum[rt*2+1];
}
void build(int l, int r, int rt)
{
    sum[rt]=0;
    if(l==r) return;
    int m=(l+r)/2;
    build(l,m,rt*2);
    build(m+1,r,rt*2+1);
}
void update(int x, int l, int r, int rt)
{
    if(l==r) 
    {
        sum[rt]=1;
        return;
    }
    int m=(l+r)/2;
    if(x<=m) update(x,l,m,rt*2);
    else update(x,m+1,r,rt*2+1);
    PushUp(rt);
}
int query(int x, int y, int l, int r, int rt)
{
    if(x>y) return 0;
    if(x<=l&&y>=r) return sum[rt];
    int m=(l+r)/2;
    int s=0;
    if(x<=m) s+=query(x,y,l,m,rt*2);
    if(y>m) s+=query(x,y,m+1,r,rt*2+1);
    return s;
}

int main()
{
    freopen("flight.in","r",stdin);
    freopen("flight.out","w",stdout);
    scanf("%d%d%d",&n,&s,&k);
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&a[i].r);
        a[i].res=i;
    }
    sort(a+1,a+n+1,cmp);
    int head=1,d=1;
    for(int i=1; i<=s; i++)
    {
        build(1,n,1);
        memset(isCalc,0,sizeof(isCalc));
        d=i;
        int tmp=0;
        while(a[head].r<i) head++;
        for(int j=head; j<=n; j++)
        {
            update(a[j].res,1,n,1);
            while(d<a[j].r)
            {
                if(!isCalc[d])
                {
                    w[i][d]=tmp;
                }
                d++;
            }
            tmp+=query(1,a[j].res-1,1,n,1);
            w[i][a[j].r]=tmp;
            isCalc[a[j].r]=1;
        }
        while(d<=s)
        {
            if(!isCalc[d])
            {
                w[i][d]=w[i][d-1];
            }
            d++;
        }
    }

    for(int i=0; i<=s; i++)
        for(int j=0; j<=k; j++)
        f[i][j]=INF;
    for(int i=1; i<=s; i++)
        f[i][1]=w[1][i];
    for(int i=2; i<=s; i++)
    {
        for(int j=2; j<=min(i,k); j++)
            for(int l=1; l<i; l++)
            {
                if(f[i][j]>f[l][j-1]+w[l+1][i])
                    f[i][j]=f[l][j-1]+w[l+1][i];
            }
    }
    printf("%d",f[s][k]);
    return 0;
}
View Code

 

正解代码O(n^2+nk)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <utility>
#include <stack>
#include <queue>
#include <map>
#include <deque>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define INF 0x3f3f3f3f
#define N 1005

using namespace std;

int w[N][N],n,s,k,f[N][N],ss[N][N],a[N];

int main()
{
    // freopen("flight.in","r",stdin);
    // freopen("flight.out","w",stdout);
    scanf("%d%d%d",&n,&s,&k);
    for(int i=1; i<=n; i++)
        scanf("%d",&a[i]);
    for(int i=1; i<=n; i++)
        for(int j=i; j<=n; j++)
        if(a[i]<a[j])
            w[a[i]][a[j]]++;    //w[i][j]表示第i排对第j排的difficulty
    for(int j=1; j<=s; j++)
    {
        for(int i=1; i<=j; i++)
            w[i][j]+=w[i-1][j];  //w[i][j]表示前i排对第j排的difficulty
        int sum=w[j][j];
        for(int i=j; i>=1; i--)
            w[i][j]=sum-w[i-1][j]; //w[i][j]表示第i-j排对第j排的difficlty
    }
    for(int i=1; i<=s; i++)
        for(int j=i; j<=s; j++)
            w[i][j]+=w[i][j-1];  //w[i][j]表示第i-j排对第i-j排的difficulty
    // for(int i=1; i<=s; i++)
    //     for(int j=i; j<=s; j++)
    //     printf("%d %d %d\n",i,j,w[i][j]);
    for(int i=0; i<=s; i++)
        for(int j=0; j<=k; j++)
        f[i][j]=INF;
    for(int i=1; i<=s; i++)
        f[i][1]=w[1][i];

    for(int j=2; j<=k; j++)
    {
        ss[s+1][j]=s-1;
        for(int i=s; i>=j; i--)
        {
            for(int l=ss[i][j-1]; l<=ss[i+1][j]; l++)
            if(f[i][j]>f[l][j-1]+w[l+1][i])
            {
                f[i][j]=f[l][j-1]+w[l+1][i];
                ss[i][j]=l;
            }
        }
    }
    printf("%d",f[s][k]);
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/Mathics/p/3917569.html

内容概要:本文档详细介绍了一个基于MATLAB实现的电力负荷预测项目,该项目运用遗传算法(GA)优化支持向量回归(SVR)和支持向量机(SVM)模型的超参数及特征选择。项目旨在解决电力系统调度、发电计划、需求侧响应等多个应用场景中的关键问题,特别是在应对高比例可再生能源接入带来的非线性、非平稳负荷预测挑战。文中涵盖了从数据接入、特征工程、模型训练到部署上线的全流程,包括详细的代码示例和GUI设计,确保方案的可复现性和实用性。 适用人群:具备一定编程基础,尤其是熟悉MATLAB语言和机器学习算法的研发人员;从事电力系统调度、电力市场交易、新能源消纳等相关领域的工程师和技术专家。 使用场景及目标:①通过构建面向小时级别的滚动预测,输出高分辨率负荷轨迹,为日内与日前滚动调度提供边际成本最小化的依据;②在负荷高峰和供给紧张时,通过价格信号或直接负荷控制实施需求侧响应,提升削峰效率并抑制反弹;③为灵活性资源(调峰机组、储能、可中断负荷)提供更清晰的出清路径,降低弃风弃光率,提升系统整体清洁度;④帮助市场主体更准确地评估边际出清价格变化,提高报价成功率与收益稳定性,同时降低由预测偏差带来的风险敞口;⑤在运维与审计场景中,对预测产生的原因进行说明,保障业务侧与监管侧的可追溯性。 阅读建议:此资源不仅提供了完整的代码实现和GUI设计,更注重于理解GA优化过程中涉及到的数据处理、特征构造、模型选择及评估等核心步骤。因此,在学习过程中,建议结合实际案例进行实践,并深入研究每个阶段的具体实现细节,特别是适应度函数的设计、超参数空间的定义以及多样性维护机制的应用。此外,关注项目中关于数据对齐、缺失值处理、特征标准化等方面的最佳实践,有助于提高模型的鲁棒性和泛化能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值