DP(递归打印路径) UVA 662 Fast Food

题目传送门

题意:n个饭店在一条直线上,给了它们的坐标,现在要建造m个停车场,饭店没有停车场的要到最近的停车场,问所有饭店到停车场的最短距离

分析:易得区间(i, j)的最短距离和一定是建在(i + j) / 2的饭店,预处理出(i, j)的距离和sum[i][j],mark[i][j] 表示区间的最优停车场的位置,mid[i][j]表示(i + j) / 2。状态转移方程:dp[i][j] = max (dp[k-1][j-1] + sum[k][i]);

收获:学习递归打印路径

代码:

/************************************************
* Author        :Running_Time
* Created Time  :2015-8-29 16:42:33
* File Name     :UVA_662.cpp
 ************************************************/

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int N = 2e2 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int dp[N][33];
int sum[N][N], d[N], mark[N][N], mid[N][N];
int n, m;
int idx;

void print(int i, int j)    {
    if (i < 1 || j < 1) return ;
    print (mark[i][j]-1, j-1);
    printf ("Depot %d at restaurant %d serves restaurant", ++idx, mid[mark[i][j]][i]);
    if (mark[i][j] == i)    {
        printf (" %d\n", i); return ;
    }
    else    printf ("s %d to %d\n", mark[i][j], i);
}

int main(void)    {
    int cas = 0;
    while (scanf ("%d%d", &n, &m) == 2) {
        if (!n && !m)   break;
        for (int i=1; i<=n; ++i)    scanf ("%d", &d[i]);
        memset (sum, 0, sizeof (sum));
        for (int i=1; i<=n; ++i)    {
            mid[i][i]=  i;
            for (int j=i+1; j<=n; ++j)    {
                int mm = (i + j) >> 1;
                mid[i][j] = mm;
                for (int k=i; k<=j; ++k)    {
                    sum[i][j] += abs (d[mm] - d[k]);
                }
            }
        }
        memset (dp, INF, sizeof (dp));
        memset (dp[0], 0, sizeof (dp[0]));
        for (int i=1; i<=n; ++i)    {
            for (int j=1; j<=m; ++j)    {
                for (int k=1; k<=i; ++k)    {
                    int tmp = dp[k-1][j-1] + sum[k][i];
                    if (dp[i][j] >= tmp) {
                        dp[i][j] = tmp;
                        mark[i][j] = k;
                    }
                }
            }
        }
        printf ("Chain %d\n", ++cas);
        idx = 0;    print (n, m);
        printf ("Total distance sum = %d\n\n", dp[n][m]);
    }

    return 0;
}

  

时间: 2024-10-26 18:29:02

DP(递归打印路径) UVA 662 Fast Food的相关文章

poj 1141 区间dp+递归打印路径

Brackets Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 30383   Accepted: 8712   Special Judge Description Let us define a regular brackets sequence in the following way: 1. Empty sequence is a regular sequence. 2. If S is a re

FatMouse&#39;s Speed ~(基础DP)打印路径的上升子序列

FatMouse believes that the fatter a mouse is, the faster it runs. To disprove this, you want to take the data on a collection of mice and put as large a subset of this data as possible into a sequence so that the weights are increasing, but the speed

UVA 662 Fast Food(DP)

The fastfood chain McBurger owns several restaurants along a highway. Recently, they have decided to build several depots along the highway, each one located at a restaurent and supplying several of the restaurants with the needed ingredients. Natura

UVa 662 - Fast Food

题目:一条街道上有n家餐馆,现在想建立k个仓库,储存代价是每个餐馆到最近的仓库的距离和: 求最小的储存代价. 分析:dp,中位数,动态规划. 状态:f(i,j)表示前j家餐馆建立i个仓库的最小储存代价: 状态转移:f(i,j)= min(f(i-1,k)+ cost(k+1,j)){ 其中 i-1 < k < j }: 其中cost(k+1,j)是在k+1,..,到j间建立一个仓库供这j-k个餐馆使用的最小单价: 此时,必然建立在中位数位置:存储路径递归逆序输出即可. 说明:之前写的不是永中位

UVA 662 Fast Food +经典动态规划

题目链接:点击进入 以前也碰到过这种类型的dp,感觉就是状态不好定义和转移:原来定义状态的时候总是认为dp[i][j]就应该由dp[i-1][j-1]转移而来,这样的话就会导致需要记忆前面i-1步的所有状态,然后就是转移方程没法写了.对于这道题,我们定义状态dp[i][j]表示前j个餐馆建立i个仓库时的最小代价,然后状态转移为dp[i][j]=dp[i-1][k-1]+cost[k][j],意思是:已经建立的前i-1个仓库负责前k-1个餐馆,然后第i个餐馆负责第k–j个餐馆,其中k<=i<=j

L2-001. 紧急救援 (Dijkstra算法打印路径)

作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上.当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队. 输入格式: 输入第一行给出4个正整数N.M.S.D,其中N(2<=N<=500)是城市的个数,顺便假设城市的编号为0~(N-1):M是快速道路的条数:S是出发地的城市编号:D是目的地的城市编号.第二行给出

uva 116 Unidirectional TSP dp + 打印路径

// uva116 Unidirectional TSP // 这题是在紫书(page 270)上看到的,个人理解就是数塔的升级版 // dp[i][j]表示从(i,j)出发到终点所达到的最大价值 // 所以很明显j是逆序的 // 状态转移方程为 // dp[i][j] = min(dp[i][j],dp[row[k]][j+1]+mp[i][j]) // rows[k]表示三行中的一行i,i-1,i+1,特判一下,排个序 // (因为多解时输出字典序最小的值) // 这题唯一比较难的地方就是打

Uva 10131 Is Bigger Smarter? (LIS,打印路径)

option=com_onlinejudge&Itemid=8&page=show_problem&problem=1072">链接:UVa 10131 题意:给定若干大象的体重及智商值.求满足大象体重严格递增,智商严格递减的序列的最大个数. 并打印随意一组取得最大值的序列的大象编号 分析:这个是LIS的应用,仅仅只是推断条件有两个,能够先对大象的体重排序,可是要打印路径. 那就必须得回溯求路径.能够直接逆序循环求,当然递归也是一个好的选择 #include<

UVa 103 - Stacking Boxes (LIS,打印路径)

链接:UVa 103 题意:给n维图形,它们的边长是{d1,d2,d3...dn},  对于两个n维图形,求满足其中一个的所有边长 按照任意顺序都一一对应小于另一个的边长,这样的最长序列的个数,并且打印任意一个最长子串的路径, 例如:a(9,5,7,3),b(6,10,8,2),c(9,7,5,1),a和b不满足,但c和b满足 分析:首先对没组边长从小到大排序,再对各组图形按最小边排序,再求最大子串, 对于打印路径,可以逆序循环,也可递归求解 #include<cstdio> #include