烽火台又称烽燧,是重要的军事防御设施,
一般建在险要处或交通要道上。
一旦有敌情发生,白天燃烧柴草,通过浓烟表达信息;
夜晚燃烧干柴,以火光传递军情。
在某两座城市之间有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];
//heap[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]
{
//1,2,5,6,2
int i;
r++;
heap[r]= ① ;//opt[k]
pos[k]=r;
② ;//home[r]=k
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;
//pos[i]表示opt[i]在堆heap中的位置,即heap[pos[i]]=opt[i]
i=pos[k];
swap(i,r);;
//1,2,5,6,2
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
③ ;//j=i+i
if(hea[i]>heap[j])
{
④ ;//swap(i,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]= ⑤ ;//value[i]+heap[1]
remove( ⑥ );//i-m
add(i);
}
cout<<heap[1]<<endl;
return 0;
}
/*
1.正确答案: opt[k]
2.正确答案: home[r] = k
3.正确答案: j = i + i(或j = 2 * i 或j = i * 2)
4.正确答案: swap(i, j)(或swap(j, i))
5.正确答案: value[i] + heap[1](或heap[1] + value[i])
6.正确答案: i - m
【王西西coding】NOIP2010提高组初赛题目分析
https://www.bilibili.com/video/BV1ha41197tb/
F[i] 1传到i最小代价
1,2,5,6,2
点燃i之前,必须先点燃[i-m,F[i-1]]区间中的某一个烽火台
F[i]=min(F[k]+value[i],k的范围 [i-m,F[i-1]])
F[i]=heap[1]+value[i]
*/
【王西西coding】NOIP2010提高组初赛题目分析
【王西西coding】c++算法竞赛NOIP提高组2010 真题讲解