传送门

参考资料:

  [1]:算法竞赛入门经典:第九章 DAG上的动态规划

题意:

  Algorithm城市的地铁有 n 个站台,编号为 1~n,共有 M1+M2 辆列车驶过;

  其中 M1 辆列车从 1 号站台驶向 n 号站台,M2 辆列车从 n 号站台驶向 1 号地铁;

  (单程线,M1 辆列车到达 n 号站台后不会回返,同理 M2)

  特工 Maria 要在 T 时刻到达 n 号站台与特务会面,但为了保证安全,在会面前尽量呆在行进的列车中;

  现给出你这 M1+M2 辆列车的发车时刻;

  问如何换乘列车使得特工 Maria 能在 T 时刻前到达 n 号站台,并且在换乘期间在站台的停留时间最短;

  如果可以在规定时间到达 n 站台,输出在站台停留的最短时间,反之,输出 "impossible";

题解:

  看完书上的解释后,感觉,不像是DAG上的动态规划,倒有点像背包的味道;

 int n,t;
int m1,m2;
int f[maxn];///前m1辆列车的发车时刻
int e[maxn];///后m2辆列车的发车时刻
int c[maxn];///c[i]:车站i到车站i+1的时间花费
/**
(i,j):i时刻在车站j
dp[i][j]:从(i,j)->(t,n)所需等待的最少时间
*/
int dp[maxn][];
/**
hasTrain[i][j][0]=true:i时刻在车站j有到j+1的火车
hasTrain[i][j][1]=true:i时刻在车站j有到j-1的火车
*/
bool hasTrain[maxn][][];

  最关键的便是dp[ i ][ j ]的定义;

  之所以定义成二维的,是因为决策受当前时间和所处车站的影响,有两个影响因素;

  定义好后,便是找状态转移方程了;

  首先预处理出 hasTrain 数组:

 void Init()///预处理hasTrain
{
mem(hasTrain,false);
for(int i=;i <= m1;++i)
{
int cnt=f[i];
hasTrain[cnt][][]=true;
for(int j=;j <= n;++j)
{
cnt += c[j-];
hasTrain[cnt][j][]=true;
}
}
for(int i=;i <= m2;++i)
{
int cnt=e[i];
hasTrain[cnt][n][]=true;
for(int j=n-;j >= ;--j)
{
cnt += c[j];
hasTrain[cnt][j][]=true;
}
}
}

预处理hasTrain[]

  令dp[t][n]=0,dp[t][1,2,...,n-1]=INF;

  按照时间逆序遍历,对于状态 dp[ i ][ j ]:

  ①等一分钟,下一分钟从车站 j 出发到达(t , n);

  ②搭乘往右开的列车;

  ③搭乘往左开的列车;

  

AC代码:

 #include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=+; int n,t;
int m1,m2;
int f[maxn];///前m1辆列车的发车时刻
int e[maxn];///后m2辆列车的发车时刻
int c[maxn];///c[i]:车站i到车站i+1的时间花费
/**
(i,j):i时刻在车站j
dp[i][j]:从(i,j)->(t,n)所需等待的最少时间
*/
int dp[maxn][];
/**
hasTrain[i][j][0]=true:i时刻在车站j有到j+1的火车
hasTrain[i][j][1]=true:i时刻在车站j有到j-1的火车
*/
bool hasTrain[maxn][][]; void Init()///预处理hasTrain
{
mem(hasTrain,false);
for(int i=;i <= m1;++i)
{
int cnt=f[i];
hasTrain[cnt][][]=true;
for(int j=;j <= n;++j)
{
cnt += c[j-];
hasTrain[cnt][j][]=true;
}
}
for(int i=;i <= m2;++i)
{
int cnt=e[i];
hasTrain[cnt][n][]=true;
for(int j=n-;j >= ;--j)
{
cnt += c[j];
hasTrain[cnt][j][]=true;
}
}
}
void Solve()
{
Init();
for(int i=;i < n;++i)
dp[t][i]=INF;
dp[t][n]=;
for(int i=t-;i >= ;--i)
{
for(int j=;j <= n;++j)
{
dp[i][j]=dp[i+][j]+;
if(j < n && hasTrain[i][j][] && i+c[j] <= t)
dp[i][j]=min(dp[i][j],dp[i+c[j]][j+]);
if(j > && hasTrain[i][j][] && i+c[j-] <= t)
dp[i][j]=min(dp[i][j],dp[i+c[j-]][j-]);
}
}
if(dp[][] >= INF)
puts("impossible");
else
printf("%d\n",dp[][]);
}
int main()
{
int kase=;
while(~scanf("%d",&n) && n)
{
scanf("%d",&t);
for(int i=;i < n;++i)
scanf("%d",c+i);
scanf("%d",&m1);
for(int i=;i <= m1;++i)
scanf("%d",f+i);
scanf("%d",&m2);
for(int i=;i <= m2;++i)
scanf("%d",e+i); printf("Case Number %d: ",++kase);
Solve();
}
return ;
}

最新文章

  1. Asp.net 加载事件(转载)
  2. winform中listview imagelist问题
  3. ccc 单点触控
  4. Html=&gt;Head=&gt;meta
  5. Nginx反向代理关于端口的问题
  6. SG函数闲扯(转)
  7. Python - 获取帮助信息
  8. CentOS 7 安装无线驱动
  9. UI2_IOS坐标系
  10. hdu 4104
  11. 图片裁切插件jCrop的使用心得(一)
  12. mysql创建存储过程中的问题
  13. step_by_step_G+入门-在线服务
  14. How many prime numbers(求素数个数)
  15. 修改emlog后台登录路径的方法(转)
  16. python变量字符拼接
  17. 将配置文件appsetting中的值转换为动态对象调用
  18. NOIP2001提高组复赛B 数的划分
  19. Docker多主机网络
  20. linux内核工作队列使用总结

热门文章

  1. JFinalConfig
  2. AlertDialog提示对话框练习
  3. iOS尽量不要在viewWillDisappear:方法中移除通知
  4. hdu4324 dfs
  5. KiCad EDA 镜像目录说明
  6. HTTP参考
  7. iOS编译错误#ld: warning: ignoring file# 之 Undefined symbols for architecture x86_64 - ld: symbol(s) not found for architecture x86_64
  8. svn总结 标签: svn开源软件 2015-05-09 17:31 513人阅读 评论(11) 收藏
  9. SDUT-2118_数据结构实验之链表三:链表的逆置
  10. Firefox浏览器怎么安装adobe flash player插件