UVA 662 - Fast Food

举报
Linux猿 发表于 2021/08/05 00:07:30 2021/08/05
【摘要】 题目链接~~> 做题感悟: 这题因为输出的时候没有看到单复数,wa了老半天,无语,净犯这些低级错误。 解题思路:                 (1) . 看这题首先想到区间 dp ,一段区间如果要找一个服务的饭店那是一定的(奇数的时候是中间的那个,偶数的时候中间的两个任意一个...

题目链接~~>

做题感悟: 这题因为输出的时候没有看到单复数,wa了老半天,无语,净犯这些低级错误。

解题思路:

                (1) . 看这题首先想到区间 dp ,一段区间如果要找一个服务的饭店那是一定的(奇数的时候是中间的那个,偶数的时候中间的两个任意一个),这样我们就可以预处理出来任意一个区间放置一个主饭店服务此区间各个饭店的路程总和,同时记录下左右区间端点值,分别用 le ,rt 代表 ,这样为下面的 dp 做好了铺垫。

动态方程:dp[ rt ] [ k ]  = min( dp[ rt ] [ k  ]  , dp [ le  -  1 ]  [  k - 1  ]  +  w )  ;  dp[  rt  ] [  k  ] 代表用 k 个主饭店服务到第 rt 个饭店最小的路程,min 括号中 dp[ rt  ] [  k  ] 代表不放置当前区间 ,dp[ le - 1 ][ k - 1 ]  +  w  代表放上当前区间 。

              (2) , 跟上面一样先处理出来 d[  i  ] [  j  ] 代表  i  ~  j  这一段区间放置一个主饭店的总路程,那么用 dp [ i ] [ j ] 代表 用了 i 个主饭店管理到第 j 个饭店的最小路程。

动态方程: dp [ i ][  j ]  = min( dp[  i  ] [  j  ]  , dp[ i - 1 ] [ k ]  +  d[ k + 1 ] [ j ] )  ;

代码(1):


      #include<iostream>
      #include<fstream>
      #include<iomanip>
      #include<ctime>
      #include<fstream>
      #include<sstream>
      #include<stack>
      #include<cstring>
      #include<cmath>
      #include<map>
      #include<vector>
      #include<cstdio>
      #include<algorithm>
      #define INT long long int
      using namespace std ;
      const double esp = 0.00000001 ;
      const int mod = 1e9 + 7 ;
      const int MY = 30 + 10 ;
      const int MX = 30000 + 10 ;
      int n ,m ,num ,k ;
      int dp[MX][MY] ,sum[MX] ,g[MX] ,pre[MX][MY] ;
      struct node
      {
      int x ,le ,rt ,w ;
      }T[MX] ;
      void DP()
      {
      int le ,rt ,w ;
      memset(dp ,0x3f ,sizeof(dp)) ;
       dp[0][0] = 0 ;
      for(int i = 0 ;i < num ;++i)
       {
       le = T[i].le ; rt = T[i].rt ;
       w = T[i].w ;
      for(int k = 1 ;k <= m ;k++)
      if(dp[rt][k] > dp[le-1][k-1] + w)
       {
       dp[rt][k] = dp[le-1][k-1] + w ;
       pre[rt][k] = i ;
       }
       }
      }
      void input()
      {
       num = 0 ;
       sum[0] = 0 ;
      for(int i = 1 ;i <= n ;i++)
       {
      scanf("%d" ,&g[i]) ;
       sum[i] = sum[i-1] + g[i] ;
       }
      for(int i = 1 ;i <= n ;i++)
      for(int j = i ;j <= n ;j++)
       {
       T[num].le = i ;
       T[num].rt = j ;
      int mid = (i + j)/2 ;
       T[num].w = g[mid]*(2*mid-i-j)+sum[j]+sum[i-1]-sum[mid]-sum[mid-1] ;
       T[num++].x = mid ;
       }
      }
      void output(int x ,int k) // 递归打印
      {
      int pi ,le ,rt ;
       pi = pre[x][k] ;
      if(k)
       {
       le = T[pi].le ;
       rt = T[pi].rt ;
       output(le-1 ,k-1) ;
      if(le != rt) //注意单复数
      cout<<"Depot "<<k<<" at restaurant "<<T[pi].x<<" serves restaurants "<<le<<" to "<<rt<<endl ;
      else cout<<"Depot "<<k<<" at restaurant "<<T[pi].x<<" serves restaurant "<<T[pi].x<<endl ;
       }
      return ;
      }
      int main()
      {
      int cse = 1 ;
      while(scanf("%d%d" ,&n ,&m) ,n+m)
       {
       input() ;
       DP() ;
      cout<<"Chain "<<cse++<<endl ;
       output(n ,m) ;
      cout<<"Total distance sum = "<<dp[n][m]<<endl ;
      cout<<endl ;
       }
      return 0 ;
      }
  
 
代码(2):


      #include<iostream>
      #include<fstream>
      #include<iomanip>
      #include<ctime>
      #include<fstream>
      #include<sstream>
      #include<stack>
      #include<cstring>
      #include<cmath>
      #include<map>
      #include<vector>
      #include<cstdio>
      #include<algorithm>
      #define INT long long int
      using namespace std ;
      const double esp = 0.00000001 ;
      const int mod = 1e9 + 7 ;
      const int MY = 30 + 10 ;
      const int MX = 200 + 10 ;
      int n ,m ,num ,k ;
      int dp[MX][MX] ,sum[MX] ,g[MX] ,pre[MX][MX] ,d[MX][MX] ;
      void DP()
      {
      memset(dp ,0x3f ,sizeof(dp)) ;
      for(int i = 1 ;i <= n ; ++i)
       dp[1][i] = d[1][i] ;
      for(int i = 2 ;i <= m ; ++i)
      for(int j = i ;j <= n ; ++j)
      for(int k = i-1 ;k < j ; ++k)
      if(dp[i][j] > dp[i-1][k] + d[k+1][j])
       {
       dp[i][j] = dp[i-1][k] + d[k+1][j] ;
       pre[i][j] = k ;
       }
      }
      void input()
      {
       num = 0 ;
       sum[0] = 0 ;
      for(int i = 1 ;i <= n ;i++)
       {
      scanf("%d" ,&g[i]) ;
       sum[i] = sum[i-1] + g[i] ;
       }
      for(int i = 1 ;i <= n ;i++)
      for(int j = i ;j <= n ;j++)
       {
      int mid = (i + j)/2 ;
       d[i][j]= g[mid]*(2*mid-i-j)+sum[j]+sum[i-1]-sum[mid]-sum[mid-1] ;
       }
      }
      void output(int k ,int x) // 递归打印
      {
      if(k)
       {
       output(k-1 ,pre[k][x]) ;
      cout<<"Depot "<<k<<" at restaurant "<<(pre[k][x]+1+x)/2<<" serves restaurants "<<pre[k][x]+1<<" to "<<x<<endl ;
       }
      return ;
      }
      int main()
      {
      int cse = 1 ;
      while(scanf("%d%d" ,&n ,&m) ,n+m)
       {
       input() ;
       DP() ;
      cout<<"Chain "<<cse++<<endl ;
       output(m ,n) ;
      cout<<"Total distance sum = "<<dp[m][n]<<endl ;
      cout<<endl ;
       }
      return 0 ;
      }
  
 






文章来源: blog.csdn.net,作者:Linux猿,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/nyist_zxp/article/details/38686763

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。