您的位置:首页 > 其它

PAT 1018. Public Bike Management (dijkstra + dfs + 剪枝)

2014-05-07 12:24 639 查看
 If there are more than one shortest path, the one that requires
the least number of bikes sent from PBMC will be chosen.

Note that if such a path is not unique, output the one that requires
minimum number of bikes that we must take back to PBMC.

因上述两个要求,光用贪心的dijkstra是不正确的。

1. dijkstra求最短路

2. dfs求出符合上述要求的路径。这个比较花心思。

3. 测试点9可能超时,需要在深搜时剪枝

dist + map[now.back()][i] <= dis[sp]


4. 注意到N是500.. 之前数组开成100了 —— 测试点9是大数据测试

5. 测试用例附在代码后面

代码:

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <list>

using namespace std;

const int INF = 2100000000;
int map[505][505];
int cmax, n, sp, m;
int has[505], dis[505], ans1, ans2;
bool vi[505];
list<int> path, tmp;

void init()
{
scanf("%d%d%d%d", &cmax, &n, &sp, &m);
for (int i = 1; i <= n; ++ i)
{
scanf("%d", has + i);
dis[i] = INF;
}
for (int i = 0; i <= n; ++ i)
{
for (int j = 0; j <= n; ++ j)
{
map[i][j] = map[j][i] = INF;
}
}
ans1 = ans2 = INF;
while (m --)
{
int x, y, dis;
scanf("%d%d%d", &x, &y, &dis);
map[x][y] = map[y][x] = dis;
}
}

void dijkstra()
{
memset(vi, 0, sizeof(vi));

dis[0] = 0;
for (int i = 0; i <= n; ++ i)
{
int v = -1, minn = INF;
for (int j = 0; j <= n; ++ j)
{
if (dis[j] < minn && vi[j] == false)
{
v = j;
minn = dis[j];
}
}
if (v == -1)
{
break;
}
vi[v] = true;
for (int j = 1; j <= n; ++ j)
{
if (dis[j] > dis[v] + map[v][j])
{
dis[j] = dis[v] + map[v][j];
}
}
}
}

bool not_in(int city, list<int>& now)
{
for (auto it = now.begin(); it != now.end(); ++ it)
{
if (*it == city)
{
return false;
}
}
return true;
}

void dfs(list<int>& now, int dist)
{
if (now.empty() == true)
{
for (int i = 1; i <= n; ++ i)
{
if (map[0][i] <= dis[sp])
{
now.push_back(i);
dfs(now, dist + map[0][i]);
now.pop_back();
}
}
return ;
}

if (now.back() == sp)
{
//		printf("lookat here\n");
int send_from = 0, take_back = 0;
for (auto it = now.begin(); it != now.end(); ++ it)
{
if (cmax/2 - has[*it] > take_back)
{
send_from += cmax/2 - has[*it] - take_back;
take_back = 0;
} else if (cmax/2 - has[*it] > 0 && cmax/2 - has[*it] <= take_back)
{
take_back -= cmax/2 - has[*it];
} else if (cmax/2 - has[*it] <= 0)
{
take_back -= cmax/2 - has[*it]; // 其实是加上了一些车
}
}
if (ans1 > 0 && send_from < ans1)
{
ans1 = send_from;
ans2 = take_back;
path = now;
} if (ans1 == send_from && take_back < ans2)
{
// ans1 = send_from;
ans2 = take_back;
path = now;
}
return ;
}

for (int i = 1; i <= n; ++ i)
{
if (map[now.back()][i] != INF
&& dist + map[now.back()][i] <= dis[sp]
&& not_in(i, now))
{
int v = now.back();
now.push_back(i);
dfs(now, dist + map[v][i]);
now.pop_back();
}
}
}

void print()
{
printf("%d 0", ans1);
for (auto it = path.begin(); it != path.end(); ++ it)
{
printf("->%d", *it);
}
printf(" %d\n", ans2);
}

int main()
{
init();

dijkstra();

dfs(tmp, 0);

print();

return 0;
}


测试用例:

10 3 3 3

6 7 0

0 1 1

0 2 1

0 3 3

10 3 3 3

6 7 9

0 1 1

0 2 1

0 3 3

10 5 5 6

8 7 0 0 5

0 1 1

0 2 1

1 3 1

2 4 1

3 5 1

4 5 1

10 5 5 6

3 4 7 6 5

0 1 1

0 2 1

1 3 1

2 4 1

3 5 1

4 5 1
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  PAT Dijkstra dfs 剪枝