博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
UVA 12295 Optimal Symmetric Paths
阅读量:6147 次
发布时间:2019-06-21

本文共 8043 字,大约阅读时间需要 26 分钟。

UVA_12295

    之前最早使用SPFA+qsort实现的优先队列写的这个题目,今天又重新用不同的方式写了一遍这个题目,即SPFA+手写堆实现的优先队列,SPFA+记忆化搜索,在Dij的过程中顺便记录路径条数等这样三种方式。

    写完之后,和预想的一样SPFA+手写堆实现的优先队列是最慢的,但对于剩下两个写法感觉得到的结论和网上看到的一篇文章写的不太一样,他说对于网格类数据Dij要明显比SPFA快一些,但就我的测试结果来看,实际上SPFA最后再加一个记忆化搜索所需的时间都要比Dij更快一些(Dij只是顺便记录了路径条数)。当然,也有可能是我自己写的堆优化的Dij效率比较低,而且我在本地用的是1000组N为100的符合题意的随机数据测的,因此也有可能SPFA更擅长处理随机数据?

 

//SPFA+手写堆实现的优先队列 #include
#include
#define MAXN 110 #define MAXD 10010 #define INF 1000000000 #define MOD 1000000009 int N, M, a[MAXN][MAXN]; long long int f[MAXD]; int q[MAXD], inq[MAXD], d[MAXD], vis[MAXD], min, tree[4 * MAXD]; int dx[] = {-1, 1, 0, 0}, dy[] = {
0, 0, -1, 1}; int init() {
int i, j; scanf("%d", &N); if(!N) return 0; for(i = 0; i < N; i ++) for(j = 0; j < N; j ++) scanf("%d", &a[i][j]); for(i = 0; i < N; i ++) for(j = 0; j < N - i - 1; j ++) a[i][j] += a[N - 1 - j][N - 1 - i]; return 1; } void SPFA() {
int i, j, k, z, newz, x, y, newx, newy, front, rear; for(i = 0; i < MAXD; i ++) d[i] = INF; d[1] = a[0][0]; memset(inq, 0, sizeof(inq)); front = rear = 0; q[rear ++] = 1; while(front != rear) {
z = q[front ++]; if(front > N * N) front = 0; inq[z] = 0; x = (z - 1) / N; y = (z - 1) % N; if(x + y == N - 1) continue; for(i = 0; i < 4; i ++) {
newx = x + dx[i]; newy = y + dy[i]; if(newx >= 0 && newx < N && newy >= 0 && newy < N) {
newz = newx * N + newy + 1; if(d[z] + a[newx][newy] < d[newz]) {
d[newz] = d[z] + a[newx][newy]; if(!inq[newz]) {
q[rear ++] = newz; if(rear > N * N) rear = 0; inq[newz] = 1; } } } } } } void insert(int x) {
int i = x + M; tree[i] = x; for(; i ^ 1; i >>= 1) tree[i >> 1] = d[tree[i]] < d[tree[i ^ 1]] ? tree[i] : tree[i ^ 1]; } void del(int x) {
int i = x + M; tree[i] = 0; for(; i ^ 1; i >>= 1) tree[i >> 1] = d[tree[i]] < d[tree[i ^ 1]] ? tree[i] : tree[i ^ 1]; } void DP() {
int i, j, k, z, x, y, newx, newy, newz; memset(f, 0, sizeof(f)); memset(tree, 0, sizeof(tree)); memset(vis, 0, sizeof(vis)); for(M = 1; M < N * N + 2; M <<= 1); f[1] = 1; insert(1); for(; tree[1];) {
z = tree[1]; x = (z - 1) / N; y = (z - 1) % N; del(z); if(x + y == N - 1) continue; for(i = 0; i < 4; i ++) {
newx = x + dx[i]; newy = y + dy[i]; if(newx >= 0 && newx < N && newy >= 0 && newy < N) {
newz = newx * N + newy + 1; if(d[z] + a[newx][newy] == d[newz]) {
f[newz] += f[z]; if(!vis[newz]) {
vis[newz] = 1; insert(newz); } } } } } } void solve() {
int i, j, k; long long int ans; SPFA(); DP(); min = INF; for(i = 0; i < N; i ++) if(d[i * N + N - i] < min) min = d[i * N + N - i]; ans = 0; for(i = 0; i < N; i ++) if(d[i * N + N - i] == min) ans = (ans + f[i * N + N - i]) % MOD; printf("%lld\n", ans); } int main() {
while(init()) {
solve(); } return 0; }

 

//SPFA+记忆化搜索 #include
#include
#define MAXN 110 #define MAXD 10010 #define INF 1000000000 #define MOD 1000000009 int N, M, a[MAXN][MAXN]; long long int f[MAXD]; int q[MAXD], inq[MAXD], d[MAXD], vis[MAXD], min, tree[4 * MAXD]; int dx[] = {-1, 1, 0, 0}, dy[] = {
0, 0, -1, 1}; int init() {
int i, j; scanf("%d", &N); if(!N) return 0; for(i = 0; i < N; i ++) for(j = 0; j < N; j ++) scanf("%d", &a[i][j]); for(i = 0; i < N; i ++) for(j = 0; j < N - i - 1; j ++) a[i][j] += a[N - 1 - j][N - 1 - i]; return 1; } void SPFA() {
int i, j, k, z, newz, x, y, newx, newy, front, rear; for(i = 0; i < MAXD; i ++) d[i] = INF; d[1] = a[0][0]; memset(inq, 0, sizeof(inq)); front = rear = 0; q[rear ++] = 1; while(front != rear) {
z = q[front ++]; if(front > N * N) front = 0; inq[z] = 0; x = (z - 1) / N; y = (z - 1) % N; if(x + y == N - 1) continue; for(i = 0; i < 4; i ++) {
newx = x + dx[i]; newy = y + dy[i]; if(newx >= 0 && newx < N && newy >= 0 && newy < N) {
newz = newx * N + newy + 1; if(d[z] + a[newx][newy] < d[newz]) {
d[newz] = d[z] + a[newx][newy]; if(!inq[newz]) {
q[rear ++] = newz; if(rear > N * N) rear = 0; inq[newz] = 1; } } } } } } long long int DP(int cur) {
int i, x, y, newx, newy, newz; if(f[cur] != -1) return f[cur]; x = (cur - 1) / N; y = (cur - 1) % N; if(x + y == N - 1) {
if(d[cur] == min) f[cur] = 1; else f[cur] = 0; return f[cur]; } f[cur] = 0; for(i = 0; i < 4; i ++) {
newx = x + dx[i]; newy = y + dy[i]; if(newx >= 0 && newx < N && newy >= 0 && newy < N) {
newz = newx * N + newy + 1; if(d[cur] + a[newx][newy] == d[newz]) f[cur] += DP(newz); } } return f[cur]; } void solve() {
int i, j, k; long long int ans; SPFA(); min = INF; for(i = 0; i < N; i ++) if(d[i * N + N - i] < min) min = d[i * N + N - i]; memset(f, -1, sizeof(f)); ans = DP(1); printf("%lld\n", ans); } int main() {
while(init()) {
solve(); } return 0; }

 

//在Dij过程中顺便记录路径条数 #include
#include
#define MAXN 110 #define MAXD 10010 #define INF 1000000000 #define MOD 1000000009 int N, M, a[MAXN][MAXN]; long long int f[MAXD]; int q[MAXD], inq[MAXD], d[MAXD], min, tree[4 * MAXD]; int dx[] = {-1, 1, 0, 0}, dy[] = {
0, 0, -1, 1}; int init() {
int i, j; scanf("%d", &N); if(!N) return 0; for(i = 0; i < N; i ++) for(j = 0; j < N; j ++) scanf("%d", &a[i][j]); for(i = 0; i < N; i ++) for(j = 0; j < N - i - 1; j ++) a[i][j] += a[N - 1 - j][N - 1 - i]; return 1; } void insert(int x) {
int i = x + M; tree[i] = x; for(; i ^ 1; i >>= 1) tree[i >> 1] = d[tree[i]] < d[tree[i ^ 1]] ? tree[i] : tree[i ^ 1]; } void del(int x) {
int i = x + M; tree[i] = 0; for(; i ^ 1; i >>= 1) tree[i >> 1] = d[tree[i]] < d[tree[i ^ 1]] ? tree[i] : tree[i ^ 1]; } void dij() {
int i, j, k, z, x, y, newx, newy, newz; memset(f, 0, sizeof(f)); memset(tree, 0, sizeof(tree)); for(M = 1; M < N * N + 2; M <<= 1); f[1] = 1; for(i = 0; i < MAXD; i ++) d[i] = INF; d[1] = a[0][0]; insert(1); for(; tree[1];) {
z = tree[1]; x = (z - 1) / N; y = (z - 1) % N; del(z); if(x + y == N - 1) continue; for(i = 0; i < 4; i ++) {
newx = x + dx[i]; newy = y + dy[i]; if(newx >= 0 && newx < N && newy >= 0 && newy < N) {
newz = newx * N + newy + 1; if(d[z] + a[newx][newy] < d[newz]) {
d[newz] = d[z] + a[newx][newy]; f[newz] = f[z]; insert(newz); } else if(d[z] + a[newx][newy] == d[newz]) f[newz] += f[z]; } } } } void solve() {
int i, j, k; long long int ans; dij(); min = INF; for(i = 0; i < N; i ++) if(d[i * N + N - i] < min) min = d[i * N + N - i]; ans = 0; for(i = 0; i < N; i ++) if(d[i * N + N - i] == min) ans = (ans + f[i * N + N - i]) % MOD; printf("%lld\n", ans); } int main() {
while(init()) {
solve(); } return 0; }

转载地址:http://zimya.baihongyu.com/

你可能感兴趣的文章
SQL server 安装教程
查看>>
Linux下ftp和ssh详解
查看>>
跨站脚本功攻击,xss,一个简单的例子让你知道什么是xss攻击
查看>>
js时间和时间戳之间如何转换(汇总)
查看>>
js插件---图片懒加载echo.js结合 Amaze UI ScrollSpy 使用
查看>>
java中string和int的相互转换
查看>>
P1666 前缀单词
查看>>
HTML.2文本
查看>>
Ubuntu unity安装Indicator-Multiload
查看>>
解决Eclipse中新建jsp文件ISO8859-1 编码问题
查看>>
7.对象创建型模式-总结
查看>>
1、块:ion-item
查看>>
【论文阅读】Classification of breast cancer histology images using transfer learning
查看>>
移动端处理图片懒加载
查看>>
jQuery.on() 函数详解
查看>>
谈缓存和Redis
查看>>
【转】百度地图api,根据多点注标坐标范围计算地图缩放级别zoom自适应地图
查看>>
用户调研(补)
查看>>
ExtJS之开篇:我来了
查看>>
☆1018
查看>>