欧拉计划 发表于 2016-8-9 17:09:37

题目83:允许向上下左右移动的情况下从左上角到右下角的最小路径和是多少?

本帖最后由 欧拉计划 于 2016-8-9 17:39 编辑

Path sum: four ways

NOTE: This problem is a significantly more challenging version of Problem 81.

In the 5 by 5 matrix below, the minimal path sum from the top left to the bottom right, by moving left, right, up, and down, is indicated in bold red and is equal to 2297.



Find the minimal path sum, in matrix.txt (right click and "Save Link/Target As..."), a 31K text file containing a 80 by 80 matrix, from the top left to the bottom right by moving left, right, up, and down.
题目:

注意:该题目是题目 81 的一个更难的版本。

在以下这个 5×5 的矩阵中,在允许向上,下,左,右移动的情况下,从左上角到右下角的最小路径和是 2297。路径用红色标出。



包含一个 80×80 的矩阵,在允许向上,下,左,右移动的情况下,找出从左上角到右下角的最小路径和。

jerryxjr1220 发表于 2016-12-31 22:30:21

a=[for j in range(85)]
dp=[for j in range(85)]
vis=[for j in range(85)]
tot=0
way=[]
Mini=-1
Minj=-1
Min=9999999999
dx=
dy=

def find():
    global Mini
    global Minj
    global Min
    Mini=-1
    Minj=-1
    Min=9999999999
    for w in range(len(way)):
      i=way
      j=way
      for k in range(4):
            nx=i+dx
            ny=j+dy
            if nx>=0 and nx<80 and ny>=0 and ny<80 and vis==0 and dp+a<Min:
                Min=dp+a
                Mini=nx
                Minj=ny

def update():
    global tot
    global Min
    x=Mini
    y=Minj
    dp=Min
    vis=1
    way.append()
    tot+=1
    print('第',tot,'个节点确定:(',x,',',y,')')
    if x==79 and y==79:
      return True
    else:
      return False

file=open('matrix.txt')
f=file.read()
file.close()
s=f.split('\n')
for i in range(80):
    a=s.split(',')
for i in range(80):
    for j in range(80):
      a=int(a)
vis=1
dp=a
tot+=1
way.append()
while tot<6400:
    find() #找到最小的位置
    if update()==True: #更新
      break
print('bingo: ',dp)

bingo:425185

jerryxjr1220 发表于 2017-1-1 09:52:54

思路和上述方法一致,但是简化了算法,时间缩短了10倍{:5_95:}
#coding:utf-8
#initiate:
file=open('matrix.txt')
f=file.read()
file.close()
s=f.split('\n')
matrix = [[]*80 for i in range(80)]
for i in range(80):
    matrix=s.split(',')
for i in range(80):
    for j in range(80):
      matrix=int(matrix)

visited = [*80 for i in range(80)]
dp = [*80 for i in range(80)]
move = [(1,0),(-1,0),(0,1),(0,-1)]
checklist = [(0,0)]
dp = 4445

#define the method for searching the best way:
def findway(x,y):
        if not visited:
                visited = True
                for m in move:
                        nx,ny = x+m,y+m
                        if 0<=nx<80 and 0<=ny<80:
                                dp = min(dp+matrix,dp)
                                checklist.append((nx,ny))

#min7979 is the min price to go:
min7979 = 999999

#repeat again and again until the min is stable, that's the answer.
while True:
        for i in range(len(checklist)):
                findway(checklist,checklist)
        if len([(j,k) for j in range(80) for k in range(80) if not visited]) == 0:
                visited = [*80 for i in range(80)]
                checklist = [(0,0)]
                if min7979 > dp:
                        min7979 = dp
                else:
                        print (min7979)
                        break
425185

najin 发表于 2017-10-11 12:27:01

用的matlab
结果是:
ans =

      425185

时间已过 0.433833 秒。
路径用matlab可以动态画出来
可惜不能上传图片

JAY饭 发表于 2018-2-21 21:03:27

import shuzimigong as sh

t = sh.t.split('\n')
s = [[] for i in range(80)]
for i in range(80):
    for each int.split(','):
      s.append(int(each))


right = {(0,0):s}
right1 = {}
t = [(-1,0),(1,0),(0,1),(0,-1)]

def move():
    count = s
    a = 0
    b = 0
    while True:
      if a == 79 and b == 79:
            break
      if a == 79 and b != 79:
            count += s
            b += 1
      elif a != 79 and b == 79:
            count += s
            a += 1
      else:   
            count += min(s,s)
            if s <= s:
                a += 1
            else:
                b += 1
    print(count)
    return count


def go(a,b,c,count):
    q = [(a,b,c)]
    while len(q) != 0:
      (a,b,c) = q.pop(0)
      
      for i in t:
            a1 = a + i
            b1 = b + i
            if 0<=a1<80 and 0<=b1<80:
                c1 = c + s
               
                if c1 <count:
                  if (a1,b1) == (79,79):
                        print(c1)
                        return c1
                  if (a1,b1) not in right:
                        
                        q.append((a1,b1,c1))
                        right[(a1,b1)] = c1
                  if (a1,b1) in right:
                        if c1 < right:
                            if (a1,b1,right[(a1,b1)]) in q:
                              q.remove((a1,b1,right[(a1,b1)]))
                           
                            right[(a1,b1)] = c1
                            right1[(a1,b1)] = (a,b)
                            q.append((a1,b1,c1))
                        
   
                  
def main():
    global right
    global right1
    count = move()
   
    while True:
      a = 0
      b = 0
      c = s
      right = {(0,0):s}
      right1 = {}
      t = go(a,b,c,count)
      if t != None:
            count = t

      else:
            print(count)
               
            break

main()

guosl 发表于 2022-1-14 21:35:33

参照上题。
/*
答案:425185
耗时:0.002039秒
*/
#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;
int m;

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, "p083_matrix.txt", "r", stdin);//打开文件
//读入数据
for (int i = 0; i < 80; ++i)
{
    for (int j = 0; j < 79; ++j)
      scanf_s("%d,", &(m));
    scanf_s("%d", &(m));
}
fclose(fin);
int nMinSum = 0x7fffffff;
char cVisited;//访问过的标志
priority_queue<stNode> q;//优先队列
//初始化数据
memset(cVisited, 0, sizeof(cVisited));
stNode nTemp;
nTemp.r = 0;
nTemp.c = 0;
nTemp.nSum = m;
cVisited = 1;
q.push(nTemp);
while (!q.empty())//广搜
{
    stNode nTop = q.top();//取出和最小的点
    q.pop();
    if (nTop.r == 79 && nTop.c == 79)//如果以到终点
    {
      nMinSum = min(nMinSum, nTop.nSum);
      break;
    }
    for (int i = 0; i < 4; ++i)//从当前点向周围四个方向探索
    {
      int nr = nTop.r + nDR;
      int nc = nTop.c + nDC;
      if (nr >= 0 && nr < 80 && nc >= 0 && nc < 80 && cVisited == 0)//检查新探索的点是否合法或尚未访问过
      {
      cVisited = 1;
      nTemp.r = nr;
      nTemp.c = nc;
      nTemp.nSum = nTop.nSum + m;
      q.push(nTemp);
      }
    }
}
t = omp_get_wtime() - t;
printf_s("%d\n%lf\n", nMinSum, t);
return 0;
}
页: [1]
查看完整版本: 题目83:允许向上下左右移动的情况下从左上角到右下角的最小路径和是多少?