题目链接~~>

做题感悟: 这题因为输出的时候没有看到单复数,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 ;
}

UVA 662 - Fast Food相关推荐

  1. UVA 662 Fast Food

    UVA_662 首先我们考虑区间[i,j]内如果建一个餐馆应该建在哪个位置,比较容易证明应该是建在中间的位置,如果是偶数个元素,中间两个位置随便一个都可以.这样我们就可以预处理出区间[i,j]内建一个 ...

  2. UVA 662 Fast Food(dp)

    题意: 一条直线马路上有n个餐馆,各个餐馆的坐标为di. 现在要在这n个餐馆中选择k个餐馆用来建造仓库. 没有仓库的餐馆,只能使用附近最近的一个仓库. 问总距离最少的建造方案,并输出. 思路: 先进行 ...

  3. UVA - 662 Fast Food

    怎么说呢,我一直希望自己能独立的想出从没见过的类型的题目,但基本上从来没有过,究竟是自己不够聪明还是说这就是变聪明的过程??但除了第二个答案我别无选择... 首先要想清楚一段restruant只有取中 ...

  4. UVA 11992 - Fast Matrix Operations(段树)

    UVA 11992 - Fast Matrix Operations 题目链接 题意:给定一个矩阵,3种操作,在一个矩阵中加入值a,设置值a.查询和 思路:因为最多20列,所以全然能够当作20个线段树 ...

  5. uva 11992 - Fast Matrix Operations

    简单的线段树的题: 有两种方法写这个题,目前用的熟是这种慢点的: 不过不知道怎么老是T: 感觉网上A过的人的时间度都好小,但他们都是用数组实现的 难道是指针比数组慢? 好吧,以后多用数组写写吧! 超时 ...

  6. uva 11992 Fast Matrix Operations

    这道题很狗血啊 赋值的时候那个v是大于等于0来着,主要考察区间赋值和更新,pushdown同时要有两个操作.代码如下: 1 #include<cstdio> 2 #include<c ...

  7. 线段树(多维+双成段更新) UVA 11992 Fast Matrix Operations

    题目传送门 题意:训练指南P207 分析:因为矩阵不超过20行,所以可以建20条线段的线段树,支持两个区间更新以及区间查询. #include <bits/stdc++.h> using ...

  8. 提取了下刘汝佳推荐的题号...

    今天闲来没事上uva oj提取了下刘汝佳推荐的acm题号,原始数据如下: Volume 0. Getting Started    10055 - Hashmat the Brave Warrior ...

  9. 【UVA】11992 - Fast Matrix Operations(段树模板)

    主体段树,要注意,因为有set和add操作,当慵懒的标志下推.递归优先set,后复发add,每次运行set行动add马克清0 WA了好几次是由于计算那一段的时候出问题了,可笑的是我对着模板找了一个多小 ...

最新文章

  1. java中锁的介绍及运用
  2. python生成表格文件_python 读取excel文件生成sql文件实例详解
  3. List、Set、Map的区别
  4. Typescript04---模块、命名空间
  5. 必须要GPT-3吗?不,BERT的MLM模型也能小样本学习
  6. Tree Recovery(二叉树递归遍历+求后序遍历模板)
  7. Unity GPU Instancing的使用尝试
  8. 二分法求正常水深c语言程序,水力學复习.doc
  9. 2018年智能手表出货量曝光 苹果Apple Watch占据半壁江山
  10. C语言 二分法查找数组元素
  11. Node.js 线程你理解的可能是错的
  12. 怎么辨别iPhone手机的真伪?
  13. MIS系统开发利器,实施、维护人员自定义报表的福音,AgileEAS.NET SOA平台动态报表指南...
  14. 计算机程序设计语言发展经历了,简述计算机程序设计语言的发展历程
  15. C语言正交表测试用例,测试用例设计之正交表法和配对测试法
  16. 软件设计师中级考试经验总结
  17. java健身房管理系统计算机毕业设计MyBatis+系统+LW文档+源码+调试部署
  18. C语言之位操作和整形的补位
  19. 奥密克戎“后遗症”,比病毒更可怕
  20. php代码生成折现统计图

热门文章

  1. 【好文分享】长文预警!高频PCB电路设计常见的66个问题
  2. 清远高考成绩查询2021年,2021年清远高考状元名单公布 今年清远高考状元是谁资料和分数...
  3. Libreoffice online集成开发
  4. AWS 认证攻略(SA)
  5. CGN与NAT444
  6. redis-migration:独创的redis在线数据迁移工具
  7. AP1236 线性LDO稳压IC 工作原理图分享
  8. 传智汇2018首秀:携手京东打造精品技术盛宴
  9. SAP FI 系列 (033) - 应收票据的接收和承兑
  10. TSINGSEE青犀视频使用海康硬盘录像机接入摄像机rtsp流步骤介绍