题目描述

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. 面试官:讲讲MySql索引失效的几种情况

    索引失效 准备数据: CREATE TABLE `dept` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `deptName` VARCHAR(30) DEFAUL ...

  2. 4.1 探索LyScript漏洞挖掘插件

    在第一章中我们介绍了x64dbg这款强大的调试软件,通过该软件逆向工程师们可以手动完成对特定进程的漏洞挖掘及脱壳等操作,虽然x64dbg支持内置Script脚本执行模块,但脚本引擎通常来说是不够强大的 ...

  3. CH32V003使用ADC八通道转换注意事项

    本文以CH32V003_F4P6(20Pin)为模板 1.PA1.PA2为外部晶振输入引脚,同时也是ADC的CH1与CH0,所以需要先在system_ch32v00x.c文件中更改为内部48M的宏即可 ...

  4. 关于 async 和 await 两个关键字(C#)【并发编程系列】

    〇.前言 对于 async 和 await 两个关键字,对于一线开发人员再熟悉不过了,到处都是它们的身影. 从 C# 5.0 时代引入 async 和 await 关键字,我们使用 async 修饰符 ...

  5. vim玩法 .vimrc配置映射指令nnoremap、inoremap

    编辑 vimrc 文件, vi ~/.vimrc vim中的映射指令,用于将一个按键绑定到某一个操作上. map: 执行映射指令,执行时会进行递归替换,可能会出现"按键循环"的情况 ...

  6. React: 路由重定向

    解决方案 参考链接 https://v5.reactrouter.com/web/example/route-config

  7. Docker版SS安装

    灰常简单 首先安装docker 使用官方安装脚本自动安装 64位的centos7和8安装命令如下: curl -fsSL https://get.docker.com | bash -s docker ...

  8. 从原理聊JVM(四):JVM中的方法调用原理

    1 引言 多态是Java语言极为重要的一个特性,可以说是Java语言动态性的根本,那么线程执行一个方法时到底在内存中经历了什么,JVM又是如何确定方法执行版本的呢? 2 栈帧 JVM中由栈帧存储方法的 ...

  9. [clickhouse]同步MySQL

    前言 clickhouse的查询速度非常快,而且兼容大部分MySQL的sql语法,因此一般将clickhouse作为MySQL的读库. 本文提供两种clickhouse同步MySQL的方式 click ...

  10. __wakeup()魔术方法绕过(CVE-2016-7124)

    __wakeup()魔术方法绕过(CVE-2016-7124) 漏洞简介 在php反序列化数据过程中,如果类中存在__wakeup方法,调用 unserilize() 方法前则先调用__wakeup方 ...