开始做usaco... & 动规 Mixing milk

 感觉usaco比HDU要好很多,虽然提交用文件输出比较麻烦,不过有个最大的好处。它会告诉你哪里出错了。

 

除开刚开始用文件提交不太习惯,AC一直顺利,有些虽然操作复杂点,调试比较麻烦,前面的题目算法都很基础。

 

 Mixing milk ,本身不难,基本的排序就可以解决,不过把条件改一下,如果每次必须把农民手中的牛奶全部买下,问题复杂很多了。

 这变成了前面说的背包问题中的第2个,那个状态运动方向要接近0但不能超过0(或者接近S但不能超过S),而Mixing milk,的状态运动方向是可以超过s(或者小于0)。依然按阶段讨论。

 定义:m[i][j]为需求为i时,第j,j+1...个阶段的最优解

  for(j=n;j>0;j--)

   for(i=1;i<=s;i++)

  {

      if(j==n)m[i][j]=0;

      else

        {

           m[i][j]=m[i][j+1];

          if(i>=v[j])m[i][j]<?m[i-v[j]][j+1]+w[j];

          else

           m[i][j]<?m[0][j]+w[j];

          }

   }

 

barn

又是牛。。。囧!

最容易想到的是假设木板无限,最短长就是有牛的牛棚个数c,最多用c个木板,若只有c-1个木板,就找到最相邻的2间把它们连起来,不断这样操作就能让木板个数为规定个数。

具体操作:

 先把stalls[]初始化为0,有牛的记录为1,然后扫一遍,把中间空的0的个数记录在另一个数组space[]中;将space[]排升序,然后按顺序c+=space[],木板m--,直到m为规定数,可跳出输出。

 

 算法没错,但我在coding时犯了许多错误,首先,扫一遍stalls时要记录begin和end,而输入不是按顺序输入编号的(开始忽略这个问题了),所以要设置2个temp记录。

 记录0个数也要记录begin和end,考虑到起点和重点的stalls[]必为1,所以判定代码如下:

 if(stalls[i]!=0&&stalls[i+1]==0)begin=i;

 if(stalls[i]==0&&stalls[i+1]!=0)end=i;

 if(begin&&end){space[t++]=end-begin-1;begin=end=0;}

(我忘记了把begin和end变成0)

 

最后计算m--时,起始的m值应该是space元素的个数+1(因为把相连的牛棚已经算做用一个木板了),忘记这样处理,结果会很大,且不知所措。(我恰好忘记这样处理了。。。囧)

 

USACO做题很爽,偶尔憋不出,还知道怎么错的。。。I LOVE MILK!~~

 

 

本文使用Blog_Backup未注册版本导出,请到soft.pt42.com注册。

你可能感兴趣的:(USACO)