zoukankan      html  css  js  c++  java
  • 题解

    作业调度方案

    https://vijos.org/p/1314

    难点提要:1 题意。 2 无。

    题意:

    好好看题就可理解。

    n个工件 m个机器 每个工件有m个工序,每个工件的每个工序需要不同的机器来做(也就是所谓的工序的机器号)

    对于安排顺序。只要每个工件的工序顺序对了即可。

    也就是说一号工件的工序1完成后才能完成一号工件的工序2

                                   2                                       3

    当一个操作插入到某台机器的某个空档时(机器上最后的尚未安排操作的部分也可以看作一个空档),可以靠前插入,也可以靠后或居中插入。为了使问题简单一些,我们约定:在保证约束条件(1)(2)的条件下,尽量靠前插入。并且,我们还约定,如果有多个空档可以插入,就在保证约束条件(1)(2)的条件下,插入到最前面的一个空档。于是,在这些约定下,上例中的方案一是正确的,而方案二是不正确的。

    做这道题关键在于理解题意。这道题让我想起了流水作业调度的Johnson算法,虽然与这道题无关。

    提示几点

    1. 每个工件的每个工序对应着不同的机器。
    2. 一个工件必须按照加工顺序加工。
    3. 把每个机器看成一个时间轴,每个时间对应着加工一个工件,或者为空闲状态。
    4. 题中的算法是给定的贪心策略,不需要构造,只要模拟。

    由于数据很小,把每个机器的时间轴用布尔数组表示,true为该时间有工件在加工,false为空闲。

    按照给定的顺序,一件一件得往时间轴上插入,每个工件插入的位置必须在前面的工序都完成以后的时间断插入。每次插入扫描一遍时间轴数组,找到最前面一个。

    其实题中所给的图已经一目了然了。理解题意以后,会发现这是NOIP2006最简单的题。

    滑雪场评级

    http://www.cnblogs.com/jznoi/p/4071616.html

    难点提要:1 思想(最小生成树的一个性质) 2 并查集的维护 

    1 思想:

       将所有点标号,并将高度差绝对值作为边长。

       先来想这样一个问题:

        要使得一棵t个节点的树,max{边权} 最小 即使得任意两点间路径上的max{边权}最小

        最小生成树中 任意两点间路径上的max{边权}是最小是a的。为什么?

             反证 假设有一条更小的边b 加进生成树 必形成一环 在做最小生成树的时候 是按边权从小到大加入 

             肯定先加入 b再加a的时候 判环 a不会加入 与假设矛盾。

      回到原题

          按边权从小到大加入 如果一个连通块有t个数了 那么 这个连通块里所有的起点的D都为新加进来的边权

        如果 某个两个连通块要合并

                其中一个连通块已经>=t了 那么 这个连通块中都不用再走了 (不可能被更新)

                如果另一个<t 那么 走哇 否则 也不走哇。

      o(n*m*2条边+dfs的时间复杂度(每个点只走一次,n*m))

      那么

    function find(x:int64):int64;

    begin
    if x=fa[x] then exit(x);
    fa[x]:=find(fa[x]);
    exit(fa[x]);
    end;
    function su(x,y:longint):int64;
    begin
    exit((x-1)*m+y);
    end;
    procedure build(x,y,x1,y1:int64);
    begin
    inc(tot);
    a[tot].x:=su(x,y);
    a[tot].y:=su(x1,y1);
    a[tot].w:=abs(b[x,y]-b[x1,y1]);
    end;
    procedure dfs(x,w:int64);
    var i,y:longint;
    begin
    flag[x]:=true;

    {dfs走的图必定是未去过的新图,所以要用flag}

    if f[x] then begin inc(ans,w); f[x]:=false; end;
    for i:=1 to h[x,0] do
    begin
    y:=h[x,i];
    if not flag[y] then dfs(y,w);
    end;
    end;
    begin
    readln(n,m,t);
    for i:=1 to n do
    begin
    for j:=1 to m do read(b[i,j]);
    readln;
    end;
    for i:=1 to n do
    begin
    for j:=1 to m do
    begin
    read(x);
    if x=1 then f[su(i,j)]:=true;
    end;
    readln;
    end;
    for i:=1 to n do
    for j:=1 to m do
    begin
    if i<n then build(i,j,i+1,j);
    if j<m then build(i,j,i,j+1);{标号建原图}
    end;
    for i:=1 to n*m do begin size[i]:=1; fa[i]:=i; end;
    sort(1,tot);
    i:=0; num:=0;
    while (i<tot) and (num<n*m-1) do
    begin
    inc(i);
    set1:=find(a[i].x); x:=a[i].x; y:=a[i].y;
    set2:=find(a[i].y);
    w:=a[i].w;
    if set1=set2 then continue;
    inc(num);
    if (size[set1]<t) and (size[set1]+size[set2]>=t) then dfs(set1,w);{只有未赋过值的连通块才要赋值}
    if (size[set2]<t) and (size[set1]+size[set2]>=t) then dfs(set2,w);
    if size[set1]<size[set2] then begin k:=set1; set1:=set2; set2:=k; end;

    //安置合并,使得size更大的连通块深度跟小 

    {一个size为500 另一个 2  如果 2的father作为500的father ,搜500连通块里数的father要多搜500次哦}
    size[set1]:=size[set1]+size[set2];
    fa[set2]:=set1;
    inc(h[x,0]); h[x,h[x,0]]:=y;{新图,其实如果连通块已经在以前的循环中赋过值了,不必去走,也不要赋边了呀}
    inc(h[y,0]); h[y,h[y,0]]:=x;[-1..n*m,-1..10]最多十条边呀
    end;
    writeln(ans);
    end.

    队伍平衡

    http://www.cnblogs.com/jznoi/p/4072697.html

    搜索也有好换之分 尽量使层数减小 即 次数减少 底数增大 更优

      枚举 人在哪个组 4的12次

      枚举 哪个组第几个位置是哪个人 12的12次

    滑雪录像

    http://www.cnblogs.com/jznoi/p/4072697.html

    贪心 按右边界排序 加入两个队列

    加入原则:

      假如两个队列都能加,加原队列右边界更远的

     -----|  ---|

    ---|  

    还是

    -----|  

    ---|     ---|

    对于这种情况无影响

    -----|  ---|

    ---|      -----|

    -----|   -----|

    ---|     ---|

    但是

    -----|  ---|

    ---|  --------|

    -----|--------|(重合了)

    ---|     ---|

    按右边界加入的证明 

    先看一条队列 两条队列也是一样

    贪心即为   

     ----   -----1    ----

     ----       ------2 --- 

    应该选谁,如果1 或2 与之前边界重合 那当然选 不重合的

      如果两条不重合 那么 选1 之后选进来的数量只增不减

    因为需要尽量多的独立的线段,所以每个线段都尽可能的小,

    对于同一右端点,左端点越大,线段长度越小。

    那么为什么要对右端点进行排序呢?

    如果左端点进行排序,那么右端点是多少并不知道,那么每一条线段都不能对之前所有的线段进行一个总结,那么这就明显

    不满足贪心的最优结构了。

    滑雪场建设

    http://www.cnblogs.com/jznoi/p/4072697.html

    难点:思路

    每次找到一个最大的正方形 最大的正方形必定是最后一步覆盖的 而前一步 这个正方形中可以为任意数,将它赋为任意数(-1)重复步骤 

    而边长更大的正方形必能被边长更小的正方形完全覆盖。反之 不成立。

    ans:=min{ 最大正方形边长} bytheway用动归或二分求最大的正方形。

    还有一点 当整个长方形全相同或最大正方形=1时退出

    旅行家的预算

    https://vijos.org/p/1253

    n=0特判 

    如果 存在两油站之间距离超过加满一次油所需时间 -1

    走 找到在当前油站k加满一次油 能走到 油价p[i]最便宜的油站i

      if p[i]>p[k] 那么在当前油站加满油再走 else 加油,走到那个油站刚好停下的油

    守望者的逃离

    https://vijos.org/p/1431

    一个s记录只用魔法能走到的距离

    另一个smax记录用最远能走到的距离

    因为守望者跑步、闪烁或休息活动均以秒(s)为单位,且每次活动的持续时间为整数秒。

    如果能用魔法就必定用,用一次1s 走路一次也是一秒。 如果无法恢复 就只能用走。。

    代码还是有点巧妙

       d:=0; dmax:=0;

      for i:=1 to t do

  • 相关阅读:
    摘录一下 上海富豪颜立燕拆借爱建资金路径曝光 暴富的关键词
    pixysoft.framework.security.sso 开发实录
    Pixysoft.Framework.Apis 开发实录
    动态加载Assembly的一系列恶心问题
    让我们开发的系统具有学习能力 我的突发奇想!
    利用RealProxy,强化AOP,在”牛粪“的周围插上”鲜花“
    Pixysoft.Applications.BugTraces 开发实录
    打造第二代测试框架TestDriven 2.0(四)—— 代码对象化建模技术
    软件工程革命三部曲 —— 外传 过程控制
    破解typemock 流水账
  • 原文地址:https://www.cnblogs.com/thedevil/p/4077165.html
Copyright © 2011-2022 走看看