poj-2709

来源:互联网 发布:什么是店铺淘宝客 编辑:程序博客网 时间:2024/09/21 09:03
//3552K 141MS Java
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;


public class Main{
private static final int BOTTLE_V = 50;
private static final int V_TYPE_MAX = 12;
private int mColorTypeNum;
private int[] mColorRequireV;
private int mGrayV;
private Comparator mCmp;


public void addRequireV(int V) {
mColorRequireV[mColorTypeNum++] = V;
}


public void setGrayV(int V) {
mGrayV = V;
}


public Main() {
mColorRequireV = new int[V_TYPE_MAX];
mCmp = new reverseComparator();
reset();
}


public class reverseComparator implements Comparator<Integer> {
@Override
public int compare(Integer p1, Integer p2) {
return p2 - p1;
}
}


public void solve() {
Arrays.sort(mColorRequireV, 0, mColorTypeNum);
int maxV = mColorRequireV[mColorTypeNum-1];
Integer colorLeft[] = new Integer[V_TYPE_MAX];
int i = 0;
for (; BOTTLE_V*i < maxV; i++) {
}
int minBottleWithoutGray = i;


// System.out.println(minBottleWithoutGray);


for (i = 0; i < mColorTypeNum; i++) {
colorLeft[i] = minBottleWithoutGray*BOTTLE_V - mColorRequireV[i];
// System.out.println(colorLeft[i]);
}


Arrays.sort(colorLeft, 0, mColorTypeNum, mCmp);


int gray_V = mGrayV;


while(true) {
// System.out.println(gray_V);
if (gray_V <= 0) {
break;
}
if (colorLeft[2] <= 0) { // no enough 3 colors to mix gray, has add bottle 
minBottleWithoutGray++;
for (i = 0; i < mColorTypeNum; i++) {
colorLeft[i] += BOTTLE_V;
// System.out.println(colorLeft[i]);
}
}
// can mix colorLeft[2] V gray

int thisTimeGrayV;
if (mColorTypeNum > 3 && colorLeft[3] > 0) {
thisTimeGrayV = colorLeft[2] - colorLeft[3] + 1;
} else {
thisTimeGrayV = colorLeft[2];
}
// System.out.println(thisTimeGrayV);
gray_V -= thisTimeGrayV;
colorLeft[0] -= thisTimeGrayV;
colorLeft[1] -= thisTimeGrayV;
colorLeft[2] -= thisTimeGrayV;
Arrays.sort(colorLeft, 0, mColorTypeNum, mCmp);
}


System.out.println(minBottleWithoutGray);
reset();
}


public void reset() {
mColorTypeNum = 0;
mGrayV = 0;
}


public static void main(String args[]) {
Main solver = new Main();
Scanner scanner = new Scanner(System.in);
while(true) {
int colorTypeNum = scanner.nextInt();
if (colorTypeNum == 0) {
return;
}
for (int i = 0; i < colorTypeNum; i++) {
solver.addRequireV(scanner.nextInt());
}
solver.setGrayV(scanner.nextInt());
solver.solve();
}

}

//3552K 141MSJava

算是个贪心水题,不过有个很重要的细节:

思路大致如下:

首先,先不考虑gray,先看其他普通颜色最少需要多少套kit, 只要找一个i使得i*50 是大于 (这些颜色中数量最多的颜色数量)的最小值即可,

i 就是能满足普通颜色数量要求的最少kit数量。

在得到i以后,就可以得到每种颜色还剩多少额外的量来得到gray的量,直接用i*50减去每种颜色的需求量即可,

贪心的选择就是,先紧着额外量最多的3种颜色来得到gray色,

这里有个重要的细节,比如有4种颜色ABCD,额外量从大到小为 V(A)>=V(B)>=V(C)>=V(D)

那么就要先从ABC三色选取一定量V来得到gray,最初想以为V取C即可,后来发现不应该只这样,

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

假设一个V1<V, 那么很有可能会有这样的情景:

在ABC都取了V1以后,额外量的大小关系就变成了 V(D)>=V(A)-V1>=V(B)-V1>=V(C)-V1,

这种情况下,按照贪心选择,就不能再从ABC中选取来配gray了,而应该从DAB中选取来配gray了,

所以,理论上讲,一应该是以1ml为单位来进行贪心选择,因为每从三种颜色各取1ml来配gray以后,颜色之间的剩余量的大小关系就有可能已经变化了,

这个思想要牢记,也反映了计算机的步进式运行.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

所以应该每配1ml的gray,就对颜色进行重排,然后选取新的前3多的颜色。

不过如果真这么搞,那么铁定TLE,如果要求1000gray,那要搞10000此重排,

因此不能以1ml为单位进行上面的操作,假设现在V(A)>=V(B)>=V(C)>=V(D)

那么可以确定,最多从ABC取 V(C)-V(D) ml来配gray, 颜色之间的大小关系是不会变化的,

因此,可以每次取 V(C)-V(D) + 1 来配gray(前提是最少4种颜色,以及 V(D)是大于0的),

还会遇到V(C)(第三多的颜色数量)已经为0,这种情况下,必须要增加kit数量了,

每种颜色的量都会增加50,

按照上面这个过程循环,直到第一次配出了>= gray要求 的gray数量.


0 0