题目描述

Vasya has recently developed a new algorithm to optimize the reception of customer flow and he considered the following problem.

Let the queue to the cashier contain n n n people, at that each of them is characterized by a positive integer ai a_{i} ai​ — that is the time needed to work with this customer. What is special about this very cashier is that it can serve two customers simultaneously. However, if two customers need ai a_{i} ai​ and aj a_{j} aj​ of time to be served, the time needed to work with both of them customers is equal to max(ai,aj) max(a_{i},a_{j}) max(ai​,aj​) . Please note that working with customers is an uninterruptable process, and therefore, if two people simultaneously come to the cashier, it means that they begin to be served simultaneously, and will both finish simultaneously (it is possible that one of them will have to wait).

Vasya used in his algorithm an ingenious heuristic — as long as the queue has more than one person waiting, then some two people of the first three standing in front of the queue are sent simultaneously. If the queue has only one customer number i i i , then he goes to the cashier, and is served within ai a_{i} ai​ of time. Note that the total number of phases of serving a customer will always be equal to ⌈n/2⌉ ⌈n/2⌉ ⌈n/2⌉ .

Vasya thinks that this method will help to cope with the queues we all hate. That's why he asked you to work out a program that will determine the minimum time during which the whole queue will be served using this algorithm.

输入格式

The first line of the input file contains a single number n n n ( 1<=n<=1000 1<=n<=1000 1<=n<=1000 ), which is the number of people in the sequence. The second line contains space-separated integers a1,a2,...,an a_{1},a_{2},...,a_{n} a1​,a2​,...,an​ ( 1<=ai<=106 1<=a_{i}<=10^{6} 1<=ai​<=106 ). The people are numbered starting from the cashier to the end of the queue.

输出格式

Print on the first line a single number — the minimum time needed to process all n n n people. Then on ⌈n/2⌉ ⌈n/2⌉ ⌈n/2⌉ lines print the order in which customers will be served. Each line (probably, except for the last one) must contain two numbers separated by a space — the numbers of customers who will be served at the current stage of processing. If n n n is odd, then the last line must contain a single number — the number of the last served customer in the queue. The customers are numbered starting from 1 1 1 .

题意翻译

一队顾客排在一位收银员前面。他采取这样一个策略:每次,假如队伍有至少两人,就会从前面的前三人(如果有)中选取两位一起收银,所花费的时间为这两人单独收银所需时间的最大值。如果只有两人,那么一起收银;如果只有一人,那么单独收银。请问所需的总时间最少是多少?

输入输出样例

输入 #1
4
1 2 3 4
输出 #1
6
1 2
3 4
输入 #2
5
2 4 3 1 4
输出 #2
8
1 3
2 5
4
考虑dp

发现不好搞,在不同的情况下选择不同的数会造成不同的影响
考虑状态的设计,发现对于不同的情况,不一样的其实是当前3个数和选到了第几个数
可以在状态中记录一下目前3个数,发现只用记录前面留下的即可

设f[i][j]表示选到了第i个数,前面留下的是第j个数时的最优解
然后就没什么了
转移应该是很显而易见的

code

//¼ÓÓÍ
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int f[1001][1001],n,a[1001],out[1001][1001][3];
inline ll read()
{
char c=getchar();ll a=0,b=1;
for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
for(;c>='0'&&c<='9';c=getchar())a=a*10+c-48;
return a*b;
}
inline void az(int i,int j,int x,int y,int z){out[i][j][0]=x;out[i][j][1]=y;out[i][j][2]=z;}
void prout(int x,int y)
{
if(y==0)return;
prout(x-1,out[x][y][2]);
if(out[x][y][0]<=n)
{
cout<<out[x][y][0]<<' ';
}
if(out[x][y][1]<=n)
{
cout<<out[x][y][1]<<' ';
}
cout<<endl;
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
n=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
}
memset(f,0x3f,sizeof(f));
f[1][1]=max(a[2],a[3]);f[1][2]=max(a[1],a[3]);f[1][3]=max(a[1],a[2]);
az(1,1,2,3,0);
az(1,2,1,3,0);
az(1,3,1,2,0);
int m=(n&1)?n/2+1:n/2;
for(int i=2;i<=m;i++)
{
int x=i<<1,y=i<<1|1;
for(int j=1;j<x;j++)
{
if(f[i][x]>f[i-1][j]+max(a[j],a[y]))
{
f[i][x]=f[i-1][j]+max(a[j],a[y]);
az(i,x,j,y,j);
}
if(f[i][y]>f[i-1][j]+max(a[j],a[x]))
{
f[i][y]=f[i-1][j]+max(a[j],a[x]);
az(i,y,j,x,j);
}
if(f[i][j]>f[i-1][j]+max(a[x],a[y]))
{
f[i][j]=f[i-1][j]+max(a[x],a[y]);
az(i,j,x,y,j);
}
}
}
cout<<f[m][n+1]<<endl;
prout(m,n+1);
return 0;
}

随机推荐

  1. Taurus .Net Core 微服务开源框架:Admin 插件【4-2】 - 配置管理-Mvc【含请求日志打印】

    前言: 继上篇:Taurus .Net Core 微服务开源框架:Admin 插件[4-1] - 配置管理-Kestrel[含https启用] 本篇继续介绍下一个内容: 1.系统配置节点:Mvc 配置 ...

  2. XTTS系列之四:迷迷糊糊的并行度

    项目测试组又反馈一个问题,XTTS执行全量备份速度慢,影响测试进度. 实际算了下,平均速度才150MB/s.. 这个速度在客户生产环境的确是不够看,首先询问是否开了并行,开了多少? 回复是说有开32个 ...

  3. ChatGPT「代码解释器」正式开放,图片转视频仅需30秒!十大令人震惊的魔法揭秘

    经过超过三个月的等待,ChatGPT「代码解释器」终于全面开放.这是一大波神奇魔法的高潮. OpenAI的科学家Karpathy对这个强大的代码解释器测试版赞不绝口.他把它比作你的个人数据分析师,可以 ...

  4. 一个高性能、低内存文件上传流.Net组件

    推荐一个用于轻松实现文件上传功能的组件. 项目简介 一个基于 .NET 平台的开源项目,提供了一个简单易用的 API,可以在 Web 应用程序中快速集成文件上传功能. 优化多部分流式文件上传性能:减少 ...

  5. Tauri-Admin通用后台管理系统|tauri+vue3+pinia桌面端后台EXE

    基于tauri+vite4+pinia2跨端后台管理系统应用实例TauriAdmin. tauri-admin 基于最新跨端技术 Tauri Rust webview2 整合 Vite4 构建桌面端通 ...

  6. Redis的设计与实现(5)-整数集合

    整数集合(intset)是集合键的底层实现之一: 当一个集合只包含整数值元素, 并且这个集合的元素数量不多时, Redis 就会使用整数集合作为集合键的底层实现. 整数集合 (intset) 是 Re ...

  7. 2023-07-25:你驾驶出租车行驶在一条有 n 个地点的路上 这 n 个地点从近到远编号为 1 到 n ,你想要从 1 开到 n 通过接乘客订单盈利。你只能沿着编号递增的方向前进,不能改变方向 乘

    2023-07-25:你驾驶出租车行驶在一条有 n 个地点的路上 这 n 个地点从近到远编号为 1 到 n ,你想要从 1 开到 n 通过接乘客订单盈利.你只能沿着编号递增的方向前进,不能改变方向 乘 ...

  8. fastposter v2.16.0 让海报开发更简单

    fastposter v2.16.0 让海报开发更简单 fastposter海报生成器是一款快速开发海报的工具.只需上传一张背景图,在对应的位置放上组件(文字.图片.二维.头像) 点击代码直接生成各种 ...

  9. 【go语言】1.1.2 Go 语言的特性

    1. 简洁的语法 Go 语言的语法设计上非常简洁明了,没有复杂的继承和泛型,也没有异常处理,但这并不影响它的功能性和表达力.这使得 Go 语言容易学习和使用. 例如,以下是一个简单的 Go 函数,用于 ...

  10. 转载【Linux中建立软raid】

    原文地址:https://www.cnblogs.com/diantong/p/10547081.html Linux内核中有一个md(multiple devices)模块在底层管理RAID设备,它 ...