对于这题一开始的思路走了误区——尝试遍历完数轴上所有的点取最小的总路程,而后发现这个其实和题意是两回事。
主要是某一个人的不满意值(等待时间)是和前面所到达过的每一个人的不满意值都关联的。
考虑无论如何只有两种情况:从出发点向上走或向下走。然后从只有两个住户的情况开始考虑解法:
用两个数组d_down[ i ][ j ]和d_up[ i ][ j ]分别表示从出发点出发,最低楼层到达了i楼,最低楼层到达了j楼的总的不满意值。其中d_down表示最后停在i,d_up表示最后停在j(i一定小于j并且i、j之间所有点都已遍历)。那么我们要求的就是d_down[ 0 ][ all-1 ]和d_up[ 0 ][ all-1 ]的最小值。
对用户楼层进行排序后我们很容易就能找到送奶工的位置start,自然d_down[ start ][ start ]和d_up[ start ][ start ]都是0。然后各自从start开始,往下递减i,往上递增j来确定每一个点的不满意值:
d_down[down][up]=min{ d_down[down+1][up]+wait_time_1,d_up[down+1][up]+wait_time_2 }
d_up[down][up]=min{ d_down[down][up-1]+wait_time_1,d_up[down][up-1]+wait_time_2 }
其中的wait_time根据不同的情况确定。
还有个要注意的是在输入用户楼层时最后还要输入送奶工的出发点,才能在后续排序中查找定位到。用a[ all++ ] 的方式同时使总值自增较为方便。
代码如下:
// Problem#: 1419
// Submission#: 3823374
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include<iostream>
#include<cstring>
using namespace std;
int d_down[1006][1006],d_up[1006][1006],node[1006];
void Sh_sort(int array[],int size)//Shell sort
{
int t,j,temp;
for(int t=size/2;t>=1;t/=2)
{
for(int i=t;i<size;i++)
{
temp=array[i];
j=i-t;
while(array[j]>temp&&j>=0)
{
array[j+t]=array[j];
j=j-t;
}
array[j+t]=temp;
}
}
}
int Get_min(int a,int b)
{
if(a<b)
{
return a;
}
else return b;
}
int Get_start(int array[],int size,int start)
{
int result;
for(int i=0;i<size;i++)
{
if(array[i]==start)
{
result=i;
break;
}
}
return result;
}
int main()
{
int cases;
cin>>cases;
while(cases--)
{
int sum,home;
cin>>sum>>home;
for(int i=0;i<sum;i++)
{
cin>>node[i];
}
node[sum++]=home;
Sh_sort(node,sum); //对用户楼层先行排序
int start,wait_time_1,wait_time_2,result;
start=Get_start(node,sum,home);
memset(d_down,100,sizeof(d_down));
memset(d_up,100,sizeof(d_up));
d_down[start][start]=0;
d_up[start][start]=0;
for(int down=start;down>=0;down--)
{
for(int up=start;up<sum;up++)
{
if(down<start)
{
wait_time_1=(node[down+1]-node[down])*(sum-(up-down));
wait_time_2=(node[up]-node[down])*(sum-(up-down));
d_down[down][up]=Get_min(d_down[down+1][up]+wait_time_1,
d_up[down+1][up]+wait_time_2);
}
if(up>start)
{
wait_time_1=(node[up]-node[down])*(sum-(up-down));
wait_time_2=(node[up]-node[up-1])*(sum-(up-down));
d_up[down][up]=Get_min(d_down[down][up-1]+wait_time_1,
d_up[down][up-1]+wait_time_2);
}
}
}
result=Get_min(d_down[0][sum-1],d_up[0][sum-1]);
cout<<result<<endl;
}
}