Codeforces Contest 82 problem D Two out of Three —— 记忆化搜索

82 篇文章 1 订阅

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 people, at that each of them is characterized by a positive integer 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 and aj of time to be served, the time needed to work with both of them customers is equal to 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, then he goes to the cashier, and is served within ai of time. Note that the total number of phases of serving a customer will always be equal to ⌈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.

Input
The first line of the input file contains a single number n (1 ≤ n ≤ 1000), which is the number of people in the sequence. The second line contains space-separated integers a1, a2, …, an (1 ≤ ai ≤ 106). The people are numbered starting from the cashier to the end of the queue.

Output
Print on the first line a single number — the minimum time needed to process all n people. Then on ⌈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 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.

Examples
inputCopy
4
1 2 3 4
outputCopy
6
1 2
3 4
inputCopy
5
2 4 3 1 4
outputCopy
8
1 3
2 5
4

题意:

给你n个数,你每次可以在前3个数中选择两个数拿出来,将答案加上这两个数的最大值,如果只有一个数那就拿一个,加上它的值,问你最后答案最小是多少。

题解:

1000的数据范围,应该想到是记忆化搜索的,但是没有。对于当前的3个值x y y+1,为什么是分开x和y呢,因为我们肯定是在前3个数中取两个,那么最多只剩下一个x,那么就是3种情况和y+2继续dfs

#include<bits/stdc++.h>
using namespace std;
const int N=1e3+5;
int dp[N][N],n,a[N];
int dfs(int x,int y)
{
    if(dp[x][y]!=-1)
        return dp[x][y];
    if(y>n)
        return dp[x][y]=a[x];
    if(y==n)
        return dp[x][y]=max(a[x],a[y]);
    dp[x][y]=max(a[x],a[y])+dfs(y+1,y+2);
    dp[x][y]=min(dp[x][y],max(a[x],a[y+1])+dfs(y,y+2));
    dp[x][y]=min(dp[x][y],max(a[y],a[y+1])+dfs(x,y+2));
    return dp[x][y];
}
void pr(int x,int y)
{
    if(y>n)
    {
        printf("%d\n",x);
        return ;
    }
    if(y==n)
    {
        printf("%d %d\n",x,y);
        return ;
    }
    if(dp[x][y]==max(a[x],a[y])+dp[y+1][y+2])
    {
        printf("%d %d\n",x,y);
        pr(y+1,y+2);
    }
    else if(dp[x][y]==max(a[x],a[y+1])+dp[y][y+2])
    {
        printf("%d %d\n",x,y+1);
        pr(y,y+2);
    }
    else
    {
        printf("%d %d\n",y,y+1);
        pr(x,y+2);
    }
}
int main()
{
    memset(dp,-1,sizeof(dp));
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    printf("%d\n",dfs(1,2));
    pr(1,2);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值