典型的光度搜索。/*
答案:260324
耗时:0.023621秒(单核)
0.005743秒(六核)
*/
#include <cstdio>
#include <algorithm>
#include <queue>
#include <omp.h>
using namespace std;
//四个方向
const int nDR[] = { 1,0,-1,0 };
const int nDC[] = { 0,1,0,-1 };
char cVisited[80][80];
int m[80][80];
struct stNode
{
int r, c;
int nSum;
bool operator<(const stNode &n) const
{
return (nSum > n.nSum);
}
};
int main(void)
{
double t = omp_get_wtime();
FILE *fin = NULL;
freopen_s(&fin, "p082_matrix.txt", "r", stdin);//打开文件
//读入数据
for (int i = 0; i < 80; ++i)
{
for (int j = 0; j < 79; ++j)
scanf_s("%d,", &(m[i][j]));
scanf_s("%d", &(m[i][79]));
}
fclose(fin);
int nMinSum = 0x7fffffff;
#pragma omp parallel for shared(m) reduction(min:nMinSum)
for (int r = 0; r < 80; ++r)//对第一列进行循环
{
char cVisited[80][80];//访问过的标志
priority_queue<stNode> q;//优先队列
//初始化数据
memset(cVisited, 0, sizeof(cVisited));
stNode nTemp;
nTemp.r = r;
nTemp.c = 0;
nTemp.nSum = m[r][0];
cVisited[r][0] = 1;
q.push(nTemp);
while (!q.empty())//广搜
{
stNode nTop = q.top();//取出和最小的点
q.pop();
if (nTop.c == 79)//如果以到终点
{
nMinSum = min(nMinSum, nTop.nSum);
break;
}
for (int i = 0; i < 4; ++i)//从当前点向周围四个方向探索
{
int nr = nTop.r + nDR[i];
int nc = nTop.c + nDC[i];
if (nr >= 0 && nr < 80 && nc >= 0 && nc < 80 && cVisited[nr][nc] == 0)//检查新探索的点是否合法或尚未访问过
{
cVisited[nr][nc] = 1;
nTemp.r = nr;
nTemp.c = nc;
nTemp.nSum = nTop.nSum + m[nr][nc];
q.push(nTemp);
}
}
}
}
t = omp_get_wtime() - t;
printf_s("%d\n%lf\n", nMinSum, t);
return 0;
}
|