正在载入在线练习界面,本页内容可直接阅读…
AK CSP › NOIP 提高 2010 第一轮真题 › 第 34 题
NOIP 提高 2010 第一轮 第 34 题:完善程序(过河问题)第 2 空
题目
2.(烽火传递)烽火台又称烽燧,是重要的军事防御设施,一般建在险要处或交通要道上。一旦有敌情发生,白天燃烧柴草,通过浓烟表达信息;夜晚燃烧干柴,以火光传递军情。在某两座城市之间有 $n$ 个烽火台,每个烽火台发出信号都有一定的代价。为了使情报准确地传递,在连续的 $m$ 个烽火台中至少要有一个发出信号。现输入 $n,m$ 和每个烽火台发出信号的代价,请计算总共最少花费多少代价,才能使敌军来袭之时,情报能在这两座城市之间准确传递。
例如,有 $5$ 个烽火台,他们发出信号的代价依次为 $1,2,5,6,2$,且 $m$ 为 $3$,则总共最少花费代价为 $4$,即由第 $2$ 个和第 $5$ 个烽火台发出信号。
#include<iostream>
#include<cstring>
using namespace std;
const int SIZE=100;
int n,m,r,value[SIZE],heap[SIZE],
pos[SIZE],home[SIZE],opt[SIZE];
//hep[i]表示用顺序数组储存的堆heap中第i个元素的值
//pos[i]表示opt[i]在堆heap中的位置,即heap[pos[i]]=opt[i]
//home[i]表示heap[i]在序列opt中的位置,即opt[home[i]]=heap[i]
void swap(int i,int j)//交换堆中的第i个和第j个元素
{
int tmp;
pos[home[i]]=j;
pos[home[j]]=i;
tmp=heap[i];
head[i]=head[j];
heap[j]=tmp;
tmp=home[i];
home[i]=home[j];
home[j]=tmp;
}
void add(int k)//在堆中插入opt[k]
{
int i;
r++;
heap[r]= ① ;
pos[k]=r;
② ;
i=r;
while( (i>1) && (heap[i]<heap[i/2]) )
{
swap(i,i/2);
i/=2;
}
}
void remove(int k)//在堆中删除opt[k]
{
int i,j;
i=pos[k];
swap(i,r);;
r--;
if(i==r+1)
return ;
while( (i>1)&&(heap[i]<heap[i/2]) )
{
swap(i,i/2);
i/=2;
}
while(i+i<=r)
{
if( (i+i+1<=r) && (heap[i+i+1]<heap[i+i]) )
j=i+i+1;
else
③ ;
if(heap[i]>heap[j])
{
④ ;
i=j;
}
else
break;
}
}
int main()
{
int i;
cin>>n>>m;
for(i=1;i<=n;i+++)
cin>>value[i];
r=0;
for(i=1;i<=m;i++)
{
opt[i]=value[i];
add(i);
}
for(i=m+1;i<=n;i++)
{
opt[i]= ⑤ ;
remove( ⑥ );
add(i);
}
cout<<heap[1]<<endl;
return 0;
}本小题
②处应填( )
答案
home[r]=k
题解
考点定位
本题(烽火传递第②空)考「位置索引维护」,对应大纲 3.2.3 堆(难度【4】)。
解题过程
②处在插入后记录 opt[k] 在堆中的位置:
``cpp home[r] = k; ``
home[i]=「堆中第 i 位元素对应 opt 的下标」,与 pos(反向索引)配对,供日后 remove(k) 定位。答案:home[r]=k。
易错提醒
① 双向索引 pos/home 是「堆中删除任意元素」的关键;② swap 时两组索引要同步交换(见程序 swap 函数)。
真题版权归 CCF 所有,本站仅用于非商业教学用途。页面加载后可直接在线作答,作答记录保存在本浏览器或账号中。 京ICP备2026056990号-1
京公网安备11010502062986号