zoukankan      html  css  js  c++  java
  • USACO 2006 Open, Problem. The Country Fair 动态规划

    题目:

    问题描述:

    每一年,John都会带着他的奶牛们去赶集。集市一共有n(1n400)个摊位,第i个摊位会在特定的时间Pi(0Pi109)对当时在摊位里的顾客送出一份精美的礼物.John当然得到了这个消息,于是他希望能拿到尽量多的礼物送给他的奶牛们。也就是说,他想尽可能多地在某摊位发放礼物的时候,正好呆在这个摊位。

    经过一定的调查,John弄清楚了从i号摊位走到j号摊位所需要的时间Ti,j (1Ti,j106)。虽然乡间小路奇特的布局使得从i号摊位走到j号摊位的最短路不一定是直接连接这两个摊位的那条,但John并不会选择那些会经过其他摊位的路线,只是直接走到目标摊位等待礼物的送出.此外,Ti,j并不一定等于Tj,i,由于John爬山的速度总是很慢.

    John在时间0时于1号摊位开始他的旅途.请你帮他设计一条路线来获得尽可能多的礼物。

    输入文件:

    第1行一个正整数n(1n400)个摊位。

    接下来n行每行一个整数Pi(0Pi109)。

    接下来一个n*n的矩阵描述Ti,j

    输出文件:

    输出仅一行一个整数,表示John最多能拿到的礼物的个数。

    样例输入输出

    cfair.in

    4
    
    13 9 19 3
    
    0 10 20 3
    
    4 0 11 2
    
    1 15 0 12
    
    5 5 13 0

    cfair.out

    3 

     

    输入输出样例说明

    一共有4家摊位。1号摊位会在时间13送出一份礼物,2号摊位送出礼物的时间为9,3号摊位是时间19,4号摊位是时间3。John先在时间3走到4号摊位,正好拿到送出的礼物.然后他再直接走到2号摊位(不经过任何中转摊位),在时间8到那儿,然后等待1单位时间,在时间9拿到摊位送出的礼物后,马上出发去1号摊位,又正好能在时间13到达并拿到第3份礼物。

    程序:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int MAX = 400 + 1;
     4 int n, g[MAX][MAX], p[MAX], f[MAX];
     5 int main()
     6 {
     7     freopen("cfair.in","r",stdin);
     8     freopen("cfair.out","w",stdout);
     9     memset(g,0,sizeof(g));
    10     cin >> n;
    11     for (int i = 1; i <= n; i++)
    12     {
    13         cin >> p[i];
    14     }
    15     for (int i = 1; i <= n; i++)
    16         for (int j = 1; j <= n; j++)
    17             cin >> g[i][j];
    18     for (int i = 1; i <= n; i++)
    19         if (g[1][i] <= p[i])
    20             f[i] = 1;
    21     bool flag = true;
    22     while (flag)
    23     {
    24         flag = false;
    25         for (int i = 1; i <= n; i++)
    26             for (int j = 1; j <= n; j++)
    27                 if (g[i][j] <= (p[j]-p[i]) && f[j] <= f[i] && i != j)
    28                 {
    29                     f[j] = f[i] + 1;
    30                     flag = true;
    31                 }
    32     }
    33     int ans = 0;
    34     for (int i = 1; i <= n; i++)
    35         ans = max(ans, f[i]);
    36     cout << ans << endl;
    37     return 0;
    38 }

    分析:

    题目不难理解,这道题的数据也不大,用矩阵就足够了。很容易理解,这是一个简单的枚举,或者叫动态规划。其他的无非就是一些套路问题了。

    if (g[i][j] <= (p[j]-p[i]) && f[j] <= f[i] && i != j)

    程序当中最终要的就是这一行,简单解释一下三个判断的作用。第一个判断意味着从摊位i领完奖品走到j时间足够再领到j摊位的奖品(路程与摊位送礼物时间的差比较)。第二个就是需要更新f[j]的值(当前值更优)。第三个判断是否是i=j,否则自己领完走到自己再领显然是错误的。

    很容易注意到,程序当中又一个非常奇怪的while()存在。但仔细想一想为什么就能明白了:因为枚举一次以后可能更新过的值还能更新别的值,这样就要反复循环,直到循环不再改编任何f数组的值为止。(flag==false)

  • 相关阅读:
    [CSS揭秘]扩大可点击区域
    [CSS揭秘]鼠标光标
    [JavaScript语法学习]全面介绍对象
    [JavaScript语法学习]全面介绍函数
    [JavaScript语法学习]全面介绍Array
    [Linux养成计划]Linux简介
    [Redis]Redis安装和使用
    [Python笔记]Python学习笔记三
    Linux_基础_文件权限
    Git_Eclipse:[8]Git分支操作
  • 原文地址:https://www.cnblogs.com/OIerPrime/p/8094645.html
Copyright © 2011-2022 走看看