阅读计划(book)

问题描述
暑假到了,Rick制定了一个长达M天的阅读计划。他一共有N本书,从1至N进行标号;Rick将它们从上至下摞成一堆。他每天都会读一本书,假设他要读编号为X的书,他会按照以下步骤:
1. 将这本书上方的所有书搬起来
2. 将这本书拿出来
3. 将搬起来的书摞回去
4. 看完后把这本书放到顶端

这里写图片描述
每本书都会有各自的重量,Rick不希望搬起太过重的书。于是他希望能重新安排这N本书的顺序,使得读完M本书之后,搬书的重量之和最小。

输入格式(book.in)
第一行两个整数N与M,分别代表书的数量和阅读的天数。
第二行N个整数,代表每本书的重量。
第三行M个整数,代表每天要读的书的编号。

输出格式(book.out)
一行一个整数,代表最小的重量之和。

样例输入
3 5
1 2 3
1 3 2 3 1

样例输出
12

数据范围与约束
对于30%的数据,N<=10.
对于100%的数据,2<=N<=500, 1<=M<=1000, 每本书重量不超过100.

解法:这是一道贪心题;
分析一下,当我们看完某一本书后,这本书一定会被放在这摞书的上面,那我们要省力的话,那不妨把它一开始就放到上面。
假如我只读一本书,那我直接放到最上的位置;
假如我只读两本书,考虑第一本书:因为无论怎样在第一天后它都会放到顶上,不
如就直接放在顶上。那第二本书放在第二个位置上是最优的。
假如我只读三本书,是类似的:考虑第三本书。在读完前两本书后,它们肯定会放
在最上方,所以放到第三位置是最优的。 (如果往上放一放,还可能给之前的其他
书增加重量)
所以我们贪心的策略就大致确定了:按照阅读的顺序从上往下放。
代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int n,m,ans; 
int a[509],r[1009],t[509],C;
bool f[509];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&r[i]);
        if(!f[r[i]]) t[++C]=r[i],f[r[i]]=1;
    }
    for(int i=1;i<=m;i++)
    {
        int j;
        for(j=1;t[j]!=r[i];ans+=a[t[j]],j++);
        for(int k=j;k>=2;k--) t[k]=t[k-1];
        t[1]=r[i];   
    }
    printf("%d",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/dfsac/p/7587878.html