Topcoder SRM642 TaroCutting

来源:互联网 发布:d2d网络 编辑:程序博客网 时间:2024/06/05 19:46

Problem Statement

 

Cat Taro has some trees in his garden. Initially, the i-th tree (0-based index) is height[i] meters tall. Each day the trees grow. For each i, the i-th tree will grow by exactly add[i] meters during each day.

Taro wants cut the trees and he has some devices to do that. For each valid i, the i-th device (0-based index) will cut any chosen tree with height greater thandevice[i] meters to exactly device[i] meters.

At the end of each day, Taro can choose any (possibly empty) subset of trees and cut them. There are two restrictions:

  • Each tree can be cut at most once per day.
  • Each device can be used at most once per day.

You are given the vector <int>s heightadd and device, and an int time. Return the smallest possible sum of the heights of the trees after time days (i.e.,time iterations of "the trees grow and then Taro cuts some of them").

Definition

 Class:TaroCuttingMethod:getNumberParameters:vector <int>, vector <int>, vector <int>, intReturns:intMethod signature:int getNumber(vector <int> height, vector <int> add, vector <int> device, int time)(be sure your method is public)

Limits

 Time limit (s):2.000Memory limit (MB):256Stack limit (MB):256

Constraints

-height will contain between 1 and 150 elements, inclusive.-height and add will contain the same number of elements.-device will contain between 1 and 150 elements, inclusive.-Each element of heightadd and device will be between 0 and 10,000, inclusive.-time will be between 1 and 150, inclusive.

Examples

0)  
{4, 7}
{7, 1}
{7}
1
Returns: 15
There are two trees. Tree 0 starts 4 meters tall and grows by 7 meters each day. Tree 1 starts 7 meters tall and grows by 1 meter each day. Thus, during the first day the first tree will grow to 4+7 = 11 meters and the second tree will grow to 7+1 = 8 meters. Taro has a single tree-cutting device that cuts a tree to 7 meters. As both trees now have more than 7 meters, he can use it on either of them. In order to minimize the sum of heights of trees, it is better to cut the taller tree: tree 0. After the cutting, the total height of trees will be 7+8 = 15 meters.1)  
{3, 1, 2}
{1, 1, 1}
{7, 7, 7}
2
Returns: 12
After two days the trees' heights will be 5, 3, and 4. The trees are still too short so Taro is unable to cut anything.  

题意:给出n颗树的高度h以及生长速度a,并给出m个设备的性能d,求最终t天后的n颗树的最小树长和。


意识:小数据加上求最小值不难想到是网络流中的最小费用流。


题解:最小费用流或者DP,这里仅仅给出最小费用流的做法。


下面给出做法。

先对题意进行转化:

最终答案对于每棵树实际上只用考虑那棵树被砍的最后一下即可(即前面不管被砍多少次,都不会影响最后一次砍的结果)即在t天以后对于每棵树i,假设它最后一下是在ti'天被砍下的,那么仅仅对于这颗树的长度 Li=(t-ti')*ai+di;另外,还有一种特殊情况,如果他一下都没被砍到,那么Li=ai*t+di。

那么ΣLi就是答案。

下面讲建图:

节点的个数一共2(起点S终点T)+1(虚拟节点G,特判不砍的情况)+树的个数+时间t+设备的个数。

在示例图中,对于每种边都标上了两个数字,左边是限制limit,右边是代价cost.

n就是tree树的个数。在这个基础上跑一发最小费用流就能得到答案。


下面只给出建图的代码://代码中n1为示例图中的n,代码中n实际为总节点的个数

int getNumber(vector <int> height, vector <int> add, vector <int> device, int time)    {        int n1=height.size();        int m=device.size();        int av=n1;        int bv=av+time;        int sv=bv+m;        int tv=sv+1;        int gv=tv+1;        n=gv+1;        for(int i=0;i<n1;i++)add_edge(sv,i),add_edge(i,gv,height[i]+add[i]*time);        for(int i=0;i<n1;i++)        {            for(int j=0;j<time;j++)add_edge(i,av+j,add[i]*j);        }        for(int i=0;i<time;i++)        {            for(int j=0;j<m;j++)add_edge(av+i,bv+j);        }        for(int i=0;i<m;i++)add_edge(bv+i,tv,device[i],time);        add_edge(gv,tv,0,n1);        return min_cost_flow(sv,tv,n1);    }


0 0