CF82D Two out of Three
题目描述
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 .
题意翻译
一队顾客排在一位收银员前面。他采取这样一个策略:每次,假如队伍有至少两人,就会从前面的前三人(如果有)中选取两位一起收银,所花费的时间为这两人单独收银所需时间的最大值。如果只有两人,那么一起收银;如果只有一人,那么单独收银。请问所需的总时间最少是多少?
输入输出样例
4
1 2 3 4
6
1 2
3 4
5
2 4 3 1 4
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;
}
随机推荐
- Unity 4.6 bate 20 or 4.5.5 +vuforia3.0.9 发布到真机错误 解决
错误图 +错误码 014-11-20 15:45:49.224 youzheng[6527:1035587] ################### enable 32014-11-20 15:45: ...
- Visual Studio Code安装C#开发工具包并编写ASP.NET Core Web应用
前言 前段时间微软发布了适用于VS Code的C#开发工具包(注意目前该包还属于预发布状态但是可以正常使用),因为之前看过网上的一些使用VS Code搭建.NET Core环境的教程看着还挺复杂的就一 ...
- 2023-07-12:RocketMQ如何做到消息不丢失?
2023-07-12:RocketMQ如何做到消息不丢失? 答案2023-07-12: RocketMQ通过刷盘机制.消息拉取机制和ACK机制等多种方式来确保消息投递的可靠性,防止消息丢失. 1.刷盘 ...
- Hexo博客Yilia主题添加相册功能,丰富博客内容,Next等其他主题可以参考
实现思路 1.在主页上必须有一个可供点击的相册连接 2.要用 hexo 生成一个photos.html文件 3.photos.html中的图片数据来源?因为这是一个静态页面所有要有一个 json文件 ...
- 数据分析之jupyter notebook工具
一.jupyter notebook介绍 1.简介 Jupyter Notebook是基于网页的用于交互计算的应用程序.其可被应用于全过程计算:开发.文档编写.运行代码和展示结果.--Jupyter ...
- 基于ClickHouse解决活动海量数据问题
1.背景 魔笛活动平台要记录每个活动的用户行为数据,帮助客服.运营.产品.研发等快速处理客诉.解决线上问题并进行相关数据分析和报警.可以预见到需要存储和分析海量数据,预估至少几十亿甚至上百亿的数据量, ...
- 一键配置 Linux 环境:zsh + tmux + vim
默认使用root用户进行安装,整个流程优化过之后,如下 curl -sSL http://119.3.1.43/pub/sh/init-terminal.sh | bash -x # 安装完成之后,重 ...
- Go语言中指针详解
指针在 Go 语言中是一个重要的特性,它允许你引用和操作变量的内存地址.下面是指针的主要作用和相关示例代码: 1. 引用传递 在 Go 中,所有的变量传递都是值传递,即复制变量的值.如果你想在一个函数 ...
- 好用工具: windows terminal
直接在微软商店搜索该软件即可,本文介绍无法使用微软商店的情况. 解题思路 当我们无法下载某个软件时,可直接去Github中寻找该项目,知道该软件资源并下载. 下载地址 https://github.c ...
- 秋叶整合包如何安装Python包
前几天写了一篇<手把手教你在本机安装Stable Diffusion秋叶整合包>的文章,有同学运行时遇到缺少Python Module的问题,帮助他处理了一下,今天把这个经验分享给大家,希 ...