模拟队列-柯南读书

题目描述 :

      柯南准备去读n本书,标号为1~n,每本书的重量为wi.柯南家太小啦,没办法放下一个书橱,于是就只好将这些书堆成一个垂直的堆,他现在想要读第x本书,他要这么做。

1.举起在x上面的所有的书

2.然后将x书从堆里面拿出来

3.将x上面的书不改变顺序地放回去

4.将x放到最上面

他决定在m天内读书,在第j天,他会读第bj (1 ≤ bj ≤ n)本书. 他取出书的方式就如同上面说的那样。

做了这样的计划之后,他突然发现作为一个一年级学生他举起想读的书上的书实在是太重了。所以他决定改变书堆的顺序(也就是初始的书是怎么堆的),从而减少总归抬起书的重量。

注意:他将x书抽出来的时候不算进抬起的重量。

输入描述 :

  给你两个整数 n (2 ≤ n ≤ 500) 和 m (1 ≤ m ≤ 1000) — 书的个数和读书的天数接下来一行有n个整数表示 w1, w2, ..., wn (1 ≤ wi ≤ 100) — 书的重量。第三行有m个整数表示每一天看什么书 b1, b2, ..., bm (1 ≤ bj ≤ n)  Note that he can read the same book more than once.

输出描述 :

  他将书堆里面的书重新排列之后最少要举起多少重量呢?

样列 :  

Input
3 5
1 2 3
1 3 2 3 1
Output
12

题解 :

       队列模拟,不过需要注意的是不一定是从尾部插入队列,好比:要看第 bj 本书,要把 1---bj-1 本书插到第 bj+1 本书之前,第 bj 本书放在首位。

#include<stdio.h>
#include<queue>
#include<set>
#include<algorithm>

using namespace std;

set<int>ss;
queue<int >qq;
int main(){
int n,m,k;
int a[505];
int b[1005];
int c[1005];
while(!qq.empty()){
qq.pop();
}
ss.clear();
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=0;i<m;i++){
scanf("%d",&b[i]);
if(!ss.count(b[i])){
ss.insert(b[i]);
qq.push(b[i]);
}
}
int sum=0;
for(int i=0;i<m;i++){
int p=1;
while(!qq.empty()){
int d=qq.front();
if(d==b[i]){
c[0]=d;
qq.pop();
break;
}
else{
sum+=a[d];
// printf("%d\n",a[d]);
   c[p++]=d;
qq.pop();
//qq.push(d);
}
}
while(!qq.empty()){
c[p++]=qq.front();
qq.pop();
}
for(int l=0;l<p;l++){
qq.push(c[l]);
}
}
printf("%d\n",sum);
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值