Codeforce 500c New Year Book Reading

来源:互联网 发布:fifaonline316普卡数据 编辑:程序博客网 时间:2024/06/05 03:23

题目大意:小明有n本书,摞起来放置,接下来的m天,每一天小明都要读一本书,当他读一本书时,需要把放在这本书上面的书搬起来,然后取出书,读完之后再放到最上面。
每本书都有重量,那么最开始这些书应该以一个怎么样的排列才能使接下来m天所需搬动的书的总重量最小。


3 5
1 2 3
1 3 2 3 1
原题配图

如图可以看出,我们应该排序为 1 3 2
这样就可以使小明所需搬书的总重量最小。

我们应该怎么解决这个问题?
既然我们是要使总重最小,而且接下来m天的读书顺序也知道了。
我们只要按照接下来的读书顺序来放置书,
即按照每本书第一次阅读的先后顺序来排书,就能避免多次搬动不必要的书了。
假设我们有七本书,重量为 3 3 2 5 4 5 1
读书顺序为 5 2 3 1 3 1 2 4 2 3
那么我们排书的顺序应该为 5 2 3 1 4 6 7
其中第七、六本书我们没有读过,所以放在最后就可以了。

接下来证明以上方法的可行性:(先考虑没有书被重复阅读的情况)
无论我们最开始以什么顺序排书,
第一天读书后,书堆上第一本书应为第一天该读的书。
第二天读书后,书堆上第一本书应为第二天该读的书,第二本书应为第一天该读的书。
第三天读书后,书堆上第一本书应为第三天该读的书,第二本书应为第二天该读的书,第一本应为第三天读的书。
……
这样的话,
第一天,如果第一天应该读的书放在最上面,就可以避免搬动不必要的书。
第二天,如果第二天应该读的书放在第二位,就可以避免搬动不必要的书。
第三天,如果第三天应该读的书放在第三位,就可以避免搬动不必要的书。
以此类推。
所以我们只需要按照读书的先后顺序排书就可以了。
理解了之后就能明白,如果把重复阅读的情况也考虑进去,也能成立。

代码如下:

#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>using namespace std;int main(){    int n,m,i,j,k,l=0;    int a[1005],b[1005],c[1005],d[1005],vis[1005]={0};    scanf("%d%d",&n,&m);    for(i=0;i<n;i++){        scanf("%d",&a[i]);        d[i]=a[i];        vis[i]=0;    }    sort(a,a+n);    for(i=0;i<m;i++){        scanf("%d",&b[i]);        if(vis[b[i]]==0){            c[l]=b[i];            l++;            vis[b[i]]=1;        }    }    for(i=0;i<n;i++){        if(vis[i]==0){            c[l]=a[i];            l++;        }    }    int sum=0;    for(i=0;i<m;i++){        for(j=0;j<n;j++){            if(c[j]==b[i]){                for(k=j;k>=1;k--){                    c[k]=c[k-1];                }                c[0]=b[i];                break;            }            sum+=d[c[j]-1];        }    }    printf("%d\n",sum);    return 0;}
原创粉丝点击