1146 - 图论你先敲完模板
Time Limit:5s Memory Limit:256MByte
Submissions:856Solved:216
DESCRIPTION
今天HH在操场上跑步,HH作为一个爱运动的人,肯定会想方设法把跑步所消耗的能量减到最少.
现在这个操场上有n个可以休息的点,他们的坐标分别为x1,x2...xn(xi≤xi+1),HH刚开始在 x1 ,并且他只能在这些点休息,在中途不能停下来,否则会因为旁边的音浪太强而被晃到.
如果HH连续跑一段长度为l的距离,那么他将会消耗2l+a的能量(a为HH的可爱值)
现在给你这些点的坐标,请帮HH计算他跑到xn点所需要消耗的能量最少是多少.
INPUT
第一行是一个整数
T(1≤T≤10),表示有
T组数据对于每组数据输入一行2个整数
n,a (1≤n≤105,1≤a≤106)表示总共有
n个休息点,
HH的可爱值为
a.接着一行
n个数
x1,x2...,xn(0≤xi≤3×106,0≤xi+1−xi≤30),表示点的位置.
OUTPUT
每组数据输出一行,一个整数,表示最小需要花费的体力
SAMPLE INPUT
23 23 5 73 103 5 7
SAMPLE OUTPUT
1226
HINT
对于第一组样例,最少的体力消耗是先从3跑到5,消耗6点体力,再从5跑到7,消耗6点体力,共12点 对于第二组样例,最少的体力消耗是直接从3跑到7,消耗26点体力.
思路:DP,
hdu2059龟兔赛跑的变形,更简单一些;
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=100005;
int pos[maxn];
ll dp[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(pos,0,sizeof(pos));
memset(dp,0x3f,sizeof(dp));
int n,a;
scanf("%d%d",&n,&a);
for(int i=1; i<=n; i++)
scanf("%d",&pos[i]);
sort(dp+1,dp+1+n);
dp[1]=0;
for(int i=2; i<=n; i++)
{
if(pos[i]==pos[i-1]) dp[i]=dp[i-1]
for(int j=i-1; j>0; j--)
{
if(pos[i]-pos[j]>62) break;
dp[i]=min(dp[i],dp[j]+a+(1LL<<(pos[i]-pos[j])));
}
}
printf("%lld\n",dp[n]);
}
return 0;
}