正在载入在线练习界面,本页内容可直接阅读…

AK CSP › NOIP 提高 2010 第一轮真题 › 第 37 题

NOIP 提高 2010 第一轮 第 37 题:完善程序(过河问题)第 5 空

完善程序 · 动态规划 · 答案 value[i]+heap[1]

题目

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;
}

本小题

⑤处应填( )

答案

value[i]+heap[1]

题解

考点定位

本题(烽火传递第⑤空)考「DP 转移取堆顶」,对应大纲 4.3.2 动态规划(难度【4】)。

解题过程

⑤处 DP 转移:f(i) = value[i] + 窗口内最小 f(堆顶):

``cpp opt[i] = value[i] + heap[1]; ``

转移后把过期的 opt[i−m] 从堆中删除(remove),新 opt[i] 入堆(add)——滑动窗口用堆维护最小值。答案:value[i]+heap[1]。

易错提醒

① 堆顶 heap[1] 是窗口内 opt 的最小值;② 本题亦可用单调队列 O(n) 完成,堆版为 O(n log n)——两种实现对照理解。

真题版权归 CCF 所有,本站仅用于非商业教学用途。页面加载后可直接在线作答,作答记录保存在本浏览器或账号中。 京ICP备2026056990号-1 京公网安备11010502062986号