[JSOI2010]Express Service 快递服务

[JSOI2010]Express Service 快递服务

Time Limit:10000MS  Memory Limit:65536K
Total Submit:84 Accepted:20
Case Time Limit:1000MS

Description

「飞奔」快递公司成立之后,已经分别与市内许多中小企业公司签订邮件收送服务契约。由于有些公司是在同一栋大楼内,所以「飞奔」公司收件的地点(收件点) 最多只有m点 (1, 2, …, m),因此「飞奔」仅先行采购了三辆货車并聘用了三名司机,每天早上分别从收件地点 「1」, 「2」 及 「3」出发。而在与客户的服务契约中有明确订约:「飞奔」必须在客户提出邮件寄送要求的隔天派人至该公司(地点)收件。
为了能更有效率的服务客户并节省收件时间,该公司设立了收件服务登记网站,客户如有邮件需要寄送,必须在需要收件的前一天就先上网登记。为了节省 油量,「飞奔」就利用晚上先行安排三位司机隔天的收件路线。每位司机至各地点收件的顺序应与各公司上网登记的顺序相符且必须能在最省油的情况下完成当天所 有的收件服务。因此每位司机有可能需要在不同时间重复到同一地点收件,或不同的司机有可能需在不同的时间点前往同一地点收件。
如下面范例二(收件公司地点依序为: 4 2 4 1 5 4 3 2 1)所示,虽然司机1一开始就已经在收件地点「1」了,但是他却不能先把后面第四个登记的公司(地点「1」)邮件先收了再前往第一、第二、或第三个登记收 件地点(地点「4」,「2」,「4」)收件。但是如果前三个登记收件的服务是由司机2或3來负责,则司机1就可以在地点「1」收了第四个登记的邮件后再前 往后面所登记的地点收件。此外,在某些情况下,不一定每辆车都要收到货,也就是說,最佳收件方式也有可能是只需出动一或兩辆车去收货。请写一个程序來帮 「飞奔」公司计算每天依预约顺序至各收件地点收件的最少总耗油量。

Input

输入文件第一行有一个整数 m(3 < = m < = 200),代表「飞奔」公司收件的地点数,以1至m之间的整数代号來表示每个地点。
接下來的m行(第2到第m+1行),每行有m个整数,代表一个矩阵D。第 i +1行的第 j 个整数是D(i, j),D(i, j) 代表司机开车从收件点 i 到收件点 j 所需耗油量。最后有一行数串,数串之数字依序为前一天上网登记要求收件的公司地点代号,最多会有1000个收件请求。输入文件中任兩个相邻的整数都以一个 空白隔开。 //D(i,j)<=maxint
注意:油量矩阵D满足三角不等式,也就是說 D(i, j) < = D(i, k) + D(k, j),1 < = i, j, k < = m。因此,每辆车前往下一个收件地点时一定是直接前往,不必先绕道至其它地点再抵达下个收件地点。

Output

输出一个整数,代表收件所需最少总耗油量。

Sample Input

4
0 5 0 6
6 0 5 6
1 6 0 6
1 1 1 0
1 1 1 1 4 4 2 2 2 3

Sample Output

6

样例说明:到每个请求收件地点的司机分别为1 1 1 1 3 3 2 2 2 1,因此司机1只需从起使点1移动到地点3,司机2只需停留在地点2,司机3从起始点3移动到地点4。

Source

JSOI2010第二轮Contest1
这题肯定是要Dp的,关键是状态,记录Dp(i,j,k)表示前i个订单,一个车在第i个订单的位置,另一个在第j个位置,另一个在第k个位置时的最小收入,那么直接Dp就OK了。。
一开始我看到那个D(i,j)<=maxint以为要用long long,结果TLE,其实这个maxint就是max integer的意思囧。。所以int就可以了。。
实际上还能再快1倍的,因为另外两辆的顺序是无所谓的,所以状态数还可以减少一半,不过懒得了囧。。

Code:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<cstring>
#define rep(i,n) for(int i=0;i<n;i++)
#define pb push_back
using namespace std;
typedef long long ll;
const int maxn=200+10,maxp=1000+10;
const int inf=~0U>>1;
int Dist[maxn][maxn];
int Dp[2][maxn][maxn];
int A[maxp],n,p=0;
void Init()
{
scanf("%d",&n);
rep(i,n) rep(j,n)scanf("%d",&Dist[i][j]);
A[p++]=0;
while(scanf("%d",A+p)==1)–A[p++];
}
inline void Update(int&x,int c){x=min(x,c);}
void Work()
{
int now=0,next=1;int cost;
rep(j,n) rep(k,n) Dp[next][j][k]=inf;
Dp[next][1][2]=0;
rep(i,p-1)
{
swap(now,next);
rep(j,n) rep(k,n) Dp[next][j][k]=inf;
rep(j,n) rep(k,n) if((cost=Dp[now][j][k])!=inf)
{
//use the car in previous place
Update(Dp[next][j][k],cost+Dist[A[i]][A[i+1]]);
//use other two car
Update(Dp[next][A[i]][j],cost+Dist[k][A[i+1]]);
Update(Dp[next][A[i]][k],cost+Dist[j][A[i+1]]);
}
}
int Ans=inf;
rep(j,n) rep(k,n) Update(Ans,Dp[next][j][k]);
cout<<Ans<<endl;
}
int main()
{
//freopen("in","r",stdin);
Init();
Work();
}

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>