[题意]给定N个点,每个点有一个停留所需的时间Ci,和停留能够获得的满意度Si,有M条边,每条边代表着两个点走动所需的时间ti,现在问在规定的T时间内从指定的一点S到E能够获得的最大的满意度是多少?要求停留的点的满意度要依次上升,并且每个点可以选择路过和停留。

好题,收获很大……

收获一:分层图的应用

收获二:越来越觉得Bellman-Ford or SPFA就是一种图上的DP,不仅仅是求最短路,更可以求某类最优问题。

收获三:像这种点有路过和停留两种状态的题目可以试着Floyd预处理,方便地处理路过的情况。

[分析]一开始我的想法是建立分层图,把每个点u分成两层,一个u表示停留,一个u' (u+n) 表示路过该点。然后建立相应的边,注意当两个边都停留时要根据满意度大小建立从小到大的有向边。需要连的边有:u->v or v -> u, u->v', u' -> v, v -> u', v' -> u, v' -> u', u' -> v'。注意用一个"超级源点"连向原来的源点s和s'(这样才是单源),然后我们做一遍二维SPFA(也就是二维Bellman-Ford)dist[time][node]表示time时间到node节点能获得的最大满意度,最后在dist[0..T][e]和dist[0..T][e+n]中找最大值就是答案。

但是超时了T_T。。。然后看了别人的题解,很漂亮。(后来对拍时发现我的程序确实是错的,不能保证从访问节点的满意度递增。。。)

先用floyd预处理出两两之间的最短距离,然后再加边,这样就可以不用处理路过节点的情况了(很精彩~想想是不是?~),所以加边时只需要考虑两个点都停留,加一条u->v or v->u即可,大大减少了边的复杂度,而且因为图中只有停留点的有向边,就保证了访问节点满意度的递增。然后又TLE了。。。跟网上的程序对了半天交了20多次终于发现是链式前向星超时了。。。。。。于是换成邻接表就过了。。。妈蛋卡常数。。。T_T
[cpp]
#define MID(x,y) ((x+y)/2)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int sup = 0x3fffffff;
const int MAXV = 105;
const int MAXE = 2015;
int cost[MAXV], value[MAXV];
struct node{
int v, t;
node(int _v, int _t){
v = _v;
t = _t;
}
};
vector arc[MAXV];
int mindis[MAXV][MAXV];
void init(int n){
value[n+1] = 0;
for (int i = 0; i <= n+1; i ++){
arc[i].clear();
for (int j = 0; j <= n+1; j ++){
if (i == j) mindis[i][i] = 0;
mindis[i][j] = sup;
}
}
}
inline void add(int u, int v, int t){
arc[u].push_back(node(v, t));
return ;
}
struct status{
int t; //time
int v; //nodes
status(int _t, int _v){
t = _t;
v = _v;
}
};
int dist[305][MAXV];
bool inq[305][MAXV];
queue Q;
inline int spfa(int n, int t, int s, int e){
for (int i = 0; i <= t; i ++)
for (int j = 0; j <= n+1; j ++){
dist[i][j] = 0;
inq[i][j] = false;
}
while(!Q.empty())
Q.pop();

dist[0][s] = 0;
inq[0][s] = 1;
Q.push(status(0, s));

while(!Q.empty()){
int u = Q.front().v;
int nowtime = Q.front().t;
Q.pop();
inq[nowtime][u] = 0;

for (int i = 0; i < (int)arc[u].size(); i ++){ int v = arc[u][i].v; int time = nowtime + arc[u][i].t; if (time > t) continue;
if (dist[time][v] < dist[nowtime][u] + value[v]){
dist[time][v] = dist[nowtime][u] + value[v];
if (!inq[time][v]){
Q.push(status(time, v));
inq[time][v] = 1;
}
}
}
}
int res = 0;
for (int i = 0; i <= t; i ++){
res = max(res, dist[i][e]);
res = max(res, dist[i][n+1]);
}
return res;
}
inline void floyd(int n){
for (int k = 0; k < n; k ++){
for (int i = 0; i < n; i ++){
for (int j = 0; j < n; j ++){
mindis[i][j] = min(mindis[i][j], mindis[i][k]+mindis[k][j]);
}
}
}
return ;
}
int main(){
int w;
scanf("%d", &w);
for (int o = 1; o <= w; o ++){
int n, m, t, s, e;
scanf("%d %d %d %d %d", &n, &m, &t, &s, &e);
init(n);
for (int i = 0; i < n; i ++){
scanf("%d", &cost[i]);
}
for (int i = 0; i < n; i ++){
scanf("%d", &value[i]);
}
for (int i = 0; i < m; i ++){
int u, v, c;
scanf("%d %d %d", &u, &v, &c);
mindis[u][v] = mindis[v][u] = min(mindis[v][u], c);
}
floyd(n);
for (int u = 0; u < n; u ++){
for (int v = u + 1; v < n; v ++){
if (mindis[u][v] != sup){
if (value[u] < value[v])
add(u, v, mindis[u][v]+cost[v]);
else if (value[v] < value[u])
add(v, u, mindis[u][v]+cost[u]);
}
}
}
add(n, s, cost[s]);
for (int i = 0; i < n; i ++){
if (i != s && mindis[s][i] != sup)
add(n, i, mindis[s][i]+cost[i]);
if (i != e && mindis[e][i] != sup)
add(i, n+1, mindis[e][i]);
}
printf("Case #%d:\n", o);
printf("%d\n", spfa(n, t, n, e));
}
return 0;
}
[/cpp]

HDU 4571 Travel in time ★(2013 ACM/ICPC长沙邀请赛)的更多相关文章

  1. HDU 4758——Walk Through Squares——2013 ACM/ICPC Asia Regional Nanjing Online

    与其说这是一次重温AC自动机+dp,倒不如说这是个坑,而且把队友给深坑了. 这个题目都没A得出来,我只觉得我以前的AC自动机的题目都白刷了——深坑啊. 题目的意思是给你两个串,每个串只含有R或者D,要 ...

  2. hdu 4751 Divide Groups bfs (2013 ACM/ICPC Asia Regional Nanjing Online 1004)

    SDUST的训练赛 当时死磕这个水题3个小时,也无心去搞其他的 按照题意,转换成无向图,预处理去掉单向的边,然后判断剩下的图能否构成两个无向完全图(ps一个完全图也行或是一个完全图+一个孤点) 代码是 ...

  3. 2013 ACM/ICPC南京邀请赛B题(求割点扩展)

    题目链接:http://icpc.njust.edu.cn/Contest/194/Problem/B B - TWO NODES 时间限制: 10000 MS 内存限制: 65535 KB 问题描述 ...

  4. 2013 ACM/ICPC 长沙网络赛J题

    题意:一个数列,给出这个数列中的某些位置的数,给出所有相邻的三个数字的和,数列头和尾处给出相邻两个数字的和.有若干次询问,每次问某一位置的数字的最大值. 分析:设数列为a1-an.首先通过相邻三个数字 ...

  5. 2013 ACM/ICPC 长沙现场赛 A题 - Alice's Print Service (ZOJ 3726)

    Alice's Print Service Time Limit: 2 Seconds      Memory Limit: 65536 KB Alice is providing print ser ...

  6. 2013 ACM/ICPC 长沙现场赛 C题 - Collision (ZOJ 3728)

    Collision Time Limit: 2 Seconds      Memory Limit: 65536 KB      Special Judge There's a round medal ...

  7. hduoj 4710 Balls Rearrangement 2013 ACM/ICPC Asia Regional Online —— Warmup

    http://acm.hdu.edu.cn/showproblem.php?pid=4710 Balls Rearrangement Time Limit: 6000/3000 MS (Java/Ot ...

  8. hduoj 4708 Rotation Lock Puzzle 2013 ACM/ICPC Asia Regional Online —— Warmup

    http://acm.hdu.edu.cn/showproblem.php?pid=4708 Rotation Lock Puzzle Time Limit: 2000/1000 MS (Java/O ...

  9. hduoj 4715 Difference Between Primes 2013 ACM/ICPC Asia Regional Online —— Warmup

    http://acm.hdu.edu.cn/showproblem.php?pid=4715 Difference Between Primes Time Limit: 2000/1000 MS (J ...

随机推荐

  1. Spark Streaming揭秘 Day17 资源动态分配

    Spark Streaming揭秘 Day17 资源动态分配 今天,让我们研究一下一个在Spark中非常重要的特性:资源动态分配. 为什么要动态分配?于Spark不断运行,对资源也有不小的消耗,在默认 ...

  2. Only the original thread that created a view hierarchy can touch its views

    在调试软件的时候出现如下的错误: 01-05 20:53:36.492: E/ZZShip(2043): android.view.ViewRootImpl$CalledFromWrongThread ...

  3. ubuntu find方法

    通用格式:find pathname -options [-print -exec -ok]例子:find / -name filename 再根目录里面搜索文件名为filename的文件find / ...

  4. easy ui datagrid 数据绑定

    1.前台页面 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> ...

  5. 【学习总结】【多线程】 线程 & 进程 & NSThread(多线程的一套API)

    一.进程和线程 1.什么是进程 进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 比如同时打开 Chrome.Xcode,系统就会分别启动2个进 ...

  6. 【BZOJ2428】[HAOI2006]均分数据

    Description 已知N个正整数:A1.A2.…….An .今要将它们分成M组,使得各组数据的数值和最平均,即各组的均方差最小.均方差公式如下: ,其中σ为均方差,是各组数据和的平均值,xi为第 ...

  7. CPU使用率

    CPU使用率 事故回放 当时的情况是那个样子的: 1,正值饭点,客户电话说系统慢,几乎无法完成订单调度,有时还显示内存不足.当时心里的第一个声音就是,服务器配置太低了,远程一看,2核4G内存,cpu平 ...

  8. 实时数据处理环境搭建flume+kafka+storm:1.zookeeper 安装配置

    1. 解压 tar -zxvf 2.创建目录  zk根目录创建         mkdir zkdatalog  --日志          mkdir zkdata  ---快照文件 3.修改配置文 ...

  9. 1189: [HNOI2007]紧急疏散evacuate - BZOJ

    Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一 ...

  10. c++ 异常处理 assert | try

    #include <iostream> #include <cassert> using namespace std; int main() { ; assert(i == ) ...