JSTSC 2010 express (CEOI 2005 service)

JSTSC 2010 express (CEOI 2005 service)

题意:
有三个邮递员A,B,C 一开始分别在地点1,2,3(M<=200),给定矩阵G,G[i][j]满足G[i][j]<=G[i][k]+G[k][j],表示i到 j的代价,每天有一封邮件(共N<=1000)在第Ni个地点,需要派一个邮递员过去,不能有两个人在同一地点,每次只能移动一个人。

做 法:
出题人没有道德  这个题是CEOI2005的service
考虑朴素做法F[T][i][j][k]表示第T天,三个邮递员各在 i,j,k,转移即枚举哪个人去。
有个优化 规定i<j<k 可以优化一般。
但是这个复杂度是无法通过此题的
注意到 第i天必然有个人要去Ni,所以可以将F[T][i][j][k]减到F[i][j][k]表示第i天另外两个邮递员在j,k
最后规定 j<k,将i维滚动,便完成了此题。

(原题还要求输出方案 在64M内存情况下只能用unsigned char记录方案,较恶心)

 1  #include  < cstdio >
 2  #include  < cstring >
 3  int  N,Q,G[ 205 ][ 205 ],list[ 1005 ];
 4  int  F[ 2 ][ 205 ][ 205 ];
 5  inline  void  Update( int   & u, int  v)
 6  {
 7       if  (u > v || u < 0 )    u = v;
 8  }
 9  int  main()
10  {
11      scanf( " %d " , & N);
12       for  ( int  i = 1 ;i <= N; ++ i)
13       for  ( int  j = 1 ;j <= N; ++ j)
14          scanf( " %d " , & G[i][j]);
15       for  (;scanf( " %d " , & list[ ++ Q]) != EOF;);
16       -- Q;
17      memset(F[ 1 ], - 1 , sizeof (F[ 1 ]));
18      F[ 1 ][ 2 ][ 3 ] = G[ 1 ][list[ 1 ]];
19      F[ 1 ][ 1 ][ 3 ] = G[ 2 ][list[ 1 ]];
20      F[ 1 ][ 1 ][ 2 ] = G[ 3 ][list[ 1 ]];
21       for  ( int  i = 1 ,pre = 1 ;i < Q; ++ i,pre ^= 1 )
22      {
23          memset(F[pre ^ 1 ], - 1 , sizeof (F[pre ^ 1 ]));
24           for  ( int  j = 1 ;j < N; ++ j)
25           for  ( int  k = j + 1 ;k <= N; ++ k)
26           if  (F[pre][j][k] >= 0 )
27          {
28               if  (list[i + 1 ] != j && list[i + 1 ] != k)
29                  Update(F[pre ^ 1 ][j][k],F[pre][j][k] + G[list[i]][list[i + 1 ]]);
30               if  (list[i + 1 ] != list[i] && list[i + 1 ] != k)
31                   if  (k < list[i])    Update(F[pre ^ 1 ][k][list[i]],F[pre][j][k] + G[j][list[i + 1 ]]);
32                   else     Update(F[pre ^ 1 ][list[i]][k],F[pre][j][k] + G[j][list[i + 1 ]]);
33               if  (list[i + 1 ] != list[i] && list[i + 1 ] != j)
34                   if  (j < list[i])    Update(F[pre ^ 1 ][j][list[i]],F[pre][j][k] + G[k][list[i + 1 ]]);
35                   else     Update(F[pre ^ 1 ][list[i]][j],F[pre][j][k] + G[k][list[i + 1 ]]);
36          }
37      }
38       int  ret = 1 << 30 ;
39       for  ( int  i = 1 ;i < N; ++ i)
40       for  ( int  j = i + 1 ;j <= N; ++ j)
41       if  (F[Q & 1 ][i][j] >= 0 )
42          Update(ret,F[Q & 1 ][i][j]);
43      printf( " %d\n " ,ret);
44       return   0 ;
45  }
46 

你可能感兴趣的:(JSTSC 2010 express (CEOI 2005 service))