D. Explorer Space(dfs+剪枝)

发布于:2025-05-12 ⋅ 阅读:(21) ⋅ 点赞:(0)

Problem - 1517D - Codeforces 

题目大意:给你一个n行m列的矩阵,以及每个点上下左右相邻点的边权,求出每个点任意走k步后再回到当前这个点的最小路程,如果不能回到起始点则输出-1

思路:既然走k步后要回到起始点,则k一定要为偶数,若为奇数则每个点输出-1,否则我们只需要求从起始点走k/2步的最小路程,注意这里不能使用Dijkstra,因为可以重复走某些点,Dijkstra走过的点如果不进行标记容易超时,所以我们考虑使用dfs+记忆化,设置一个记忆化数组dp[i][j][c]表示(i,j)这个位置再走c步的最小路程。

Code:

int n,m,k;
map<PII,int> mp;
int dp[505][505][25];
int ne[4][2]={{0,1},{0,-1},{1,0},{-1,0}};

int dfs(int x,int y,int c)
{
  if(c==0) return dp[x][y][c]=0;
  if(dp[x][y][c]) return dp[x][y][c];
  int mn=1e18;
  for(int i=0;i<4;i++)
  {
    int tx=x+ne[i][0],ty=y+ne[i][1];
    if(tx>=1&&tx<=n&&ty>=1&&ty<=m)
    {
      mn=min(mn,dfs(tx,ty,c-1)+mp[{(x-1)*m+y,(tx-1)*m+ty}]);
    }
  }

  return dp[x][y][c]=mn;
}
void solve()
{
   cin>>n>>m>>k;

   for(int i=1;i<=n;i++)
   {
     for(int j=1;j<m;j++)
     {
      int x;cin>>x;
      int a=(i-1)*m+j;
      int b=a+1;
      mp[{a,b}]=mp[{b,a}]=x; 
     }

   }

   for(int i=1;i<n;i++)
   {
    for(int j=1;j<=m;j++)
    {
      int x;cin>>x;
      int a=(i-1)*m+j;
      int b=a+m;
      mp[{a,b}]=mp[{b,a}]=x;
    }
   }
   if(k&1)
   {
    for(int i=1;i<=n;i++)
    {
      for(int j=1;j<=m;j++) cout<<-1<<' ';
        cout<<endl;
    }
    return ;
   }
   k/=2;
   for(int i=1;i<=n;i++)
   {
    for(int j=1;j<=m;j++)
    {
      cout<<dfs(i,j,k)*2<<' ';
    }
    cout<<endl;
   }
}

 


网站公告

今日签到

点亮在社区的每一天
去签到