posts - 101,  comments - 57,  trackbacks - 0
    这道题目(昂贵的聘礼)在poj上只有26%的ac率,貌似是第一道(总之是前几道第一次引入的中文题目),别以为中文题目就容易。中文题目就好理解,这题有25%的submit是因为理解错误而wa的。
    言归正传...

    题意给出几个节点要求最短的路径。

    我建立的模型是这样:括号中第一个表示钱,第二个是等级。

                +-- 8000 --(1000, 2)-- 200---+
                |                            |
    (10000, 3) -+                            +--(50, 2)
                |                            |
                +-- 5000 --(3000, 2)-- 200 --+


     第一个反映当然是“单元最短路径”dijkstra算法来做,但是WA了几次后才发现原来我理解等级错误了。

     如果A B C 的等级是 3 2 1, 而限制是1的话,那么从C -> A的路径则视为非法。

     继续做,对路径进行动态的记录。结果居然出现某些点无法到达的情况,例如:

     等级限制M = 1

                +--5000--(1000, 2)--200---+
                |                         |
    (10000, 3) -+                         +--([No.4] 200, 3)--50--([No.5] 50, 2) 
                |                         |
                +--5000--(3000, 4)--100 --+

     这种场景下,No.4节点由于dijkstra本身是一个贪心算法,所以会被下面的路径标记。但是由于等级限制的限制No.5节点会被视为非法。而此题的正解应该是走上面的路径,将No.5节点纳入计算节点中。

     这时候就是说局部的最优解不是最终的最优解(是次优解),那么dijkstra算法就不能成立了。

     那就不能用dijkstra了吗? 我看了看discus,很多人说用dp,用dfs等等...感觉很不甘心啊!

     在憋了两天之后,我终于找到了一个办法。

     直接用dijkstra肯定是不行的,如果对dijkstra做一些优化,对每个目标节点做一次dijkstra的枚举就可以避免次优解的问题,如何来做呢?

     dijkstra算法的时候,指定一个目标节点,也就是说循环计算该图的dijkstra,每次都是from 0 to i节点。

     这样就能在一开始的时候得到0节点 和 目标节点能允许的等级范围。以上图为例,当枚举到目标节点为No.5的时候,那么源节点的max_level = 3 + M = 4, min_level = 3 - 1 = 2,再计算No.5的等级限制为[1, 3]。将两个等级merge一下,就是[2, 3],也就是说从源节点所有到No.5节点的level必须在[2, 3]的范围内。

     那么在dijkstra的时候,对于level = 4的节点就被视为非法,不进入计算中。

     对dijkstra进行一些优化,比如当计算到目标节点已知的时候就可以结束了。

     还是要说这种的计算方法还是有优化的空间,毕竟在计算No.5的时候会用到前面计算的结果,可以考虑dp,但是这题的数据较弱,ac之后就不想再弄了。

     觉得上面虽然说了思路,还是给出代码吧,这样看得比较清楚,0ms ac。

  1#include <stdio.h>
  2
  3#define MAX_NODE 100
  4#define MAX_D    100000000
  5
  6int M, N;
  7
  8struct _Node
  9{
 10    int p;
 11    int l;
 12}
Node[MAX_NODE];
 13
 14int Engle[MAX_NODE][MAX_NODE] = {0};
 15
 16struct _Table
 17{
 18    int k;
 19    int d;
 20    int max_l;
 21    int min_l;
 22}
Table[MAX_NODE];
 23
 24int result = MAX_D;
 25
 26void dijkstra(int t)
 27{
 28    int i, min_d, min_n;
 29    int max_l, min_l;
 30    // init
 31    for (i = 0; i < N; ++i)
 32    {
 33        Table[i].k = 0;
 34        Table[i].d = MAX_D;
 35        Table[i].max_l = Node[i].l + M;
 36        Table[i].min_l = Node[i].l - M;
 37    }

 38    Table[0].d = 0;
 39    max_l = Table[0].max_l < Table[t].max_l ? Table[0].max_l : Table[t].max_l;
 40    min_l = Table[0].min_l > Table[t].min_l ? Table[0].min_l : Table[t].min_l;
 41    // dijkstra
 42    while (!Table[t].k)
 43    {    
 44        min_d = MAX_D;
 45        min_n = -1;
 46        // find min n;
 47        for (i = 0; i < N; i++)
 48        {
 49            if (!Table[i].k && Table[i].d < min_d)
 50            {
 51                min_d = Table[i].d;
 52                min_n = i;
 53            }

 54        }

 55        // break
 56        if (-1 == min_n)
 57            break;
 58        //
 59        for (i = 0; i < N; ++i)
 60        {
 61            if (   min_l <= Node[i].l && Node[i].l <= max_l
 62                && !Table[i].k
 63                && Engle[min_n][i]
 64                && Table[i].d > Engle[min_n][i] + Table[min_n].d)
 65            {
 66                Table[i].d = Engle[min_n][i] + Table[min_n].d;
 67            }

 68        }

 69        //
 70        Table[min_n].k = 1;
 71    }

 72    
 73    if (Table[t].k && result > Table[t].d + Node[t].p)
 74    {
 75        result = Table[t].d + Node[t].p;
 76    }

 77}

 78
 79
 80
 81void main()
 82{
 83    int P, L, X;
 84    int T, V;
 85    int i, n = 0;
 86
 87    scanf("%d %d"&M, &N);
 88    
 89    while (EOF != scanf("%d %d %d"&P, &L, &X))
 90    {
 91        Node[n].l = L;
 92        Node[n].p = P;
 93        for (i = 0; i < X; ++i)
 94        {
 95            scanf("%d %d"&T, &V);
 96            Engle[n][T - 1= V;            
 97        }

 98        n++;
 99    }

100
101    for (i = 0; i < N; ++i)
102    {
103        dijkstra(i);
104    }

105    printf("%d\n", result);        
106}





posted on 2011-05-14 00:16 margin 阅读(467) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2010年12月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

常用链接

留言簿

随笔档案

文章分类

文章档案

收藏夹

常去的坛子

  • CVC电脑病毒论坛
  • 很多人说我是AV,我告诉他们:别瞧不起人,我们也能创造价值
  • 安全焦点
  • 黑客聚集的地方,一般是好酒最多的地方...
  • 看雪论坛
  • 国内最强的加密解密论坛,成醉其中经常夜不归宿
  • 驱动开发论坛
  • 厌倦了啤的朋友们,来我们来整点白的...痛痛快快的BSOD也好过隔鞋瘙痒!

我的朋友

  • Sen的blog
  • IDE方面资深的受害者...经常为一个变量的定义找不着北的痛苦程序员(深表同情)
  • 老罗的blog
  • 良师益友,千年水牛,引擎猛男,分析怪兽,墨镜酷哥,台球高手....

搜索

  •  

最新评论