非穷举方法解决poj 1006

来源:互联网 发布:车辆保养记录查询软件 编辑:程序博客网 时间:2024/06/05 20:46
/**Author:Founder Watts *作者原创,转载请注明出处 */

非穷举方法解决poj 1006
主要思想,将问题维度不断降低,从原本的三维降到一维
设三项数据分别为a,b,c,最后天数为d
(数据修正:以b为中心,使a和c向b靠拢,并使a <= b <= c )
其中b是本问题的核心,首先进行第一次降维,以b的高峰期为基准,计算b-a和c-b他们高峰期的差值,下面为作者统计的数据:
设n为三个高峰第一次相同起,b的第n个高峰,n>=0
b-a = 5 * n (0 <= n <= 4)
= 2 + 5 * (n - 5) (5 <= n <= 9)
= 4 + 5 * (n - 10) (10 <= n <= 13)
= 1 + 5 * (n - 14) (14 <= n <= 18)
= 3 + 5 * (n - 19) (19 <= n <= 22)

c-b = 5 * n(0 <= n <= 6)
= 2 + 5 * (n - 7) (7 <= n <= 13)
= 4 + 5 * (n - 14) (14 <= n <= 19)
= 1 + 5 * (n - 20) (20 <= n <= 26)
= 3 + 5 * (n - 27) (27 <= n <= 32)

有了上面的公式,我们就能以a与b之间的差和b与c之间的差完成第一次降维,下面开始第二次降维
假设通过代入数据求出 b-a 的高峰数n为p, c-b 的高峰数n为q,此时以b-a为基准进行降维
(数据修正:使q >= p,若 q < p,使 q = q + 33,p 不要变)
设m为b-a进行的轮数,通过公式 (m - 1) * 23 % 33 = (q - p)求出第m轮时,b-a中的n=0对应c-b中的n为多少,下面是作者算出的对照关系:
1:0 2:23 3:13 4:3 5:26 6:16 7:6 8:29 9:19 10:9 11:32 12:22 13:12 14:2 15:25 16:15 17:5 18:28 19:18
20:8 21:31 22:21 23:11 24:1 25:24 26:14 27:4 28:27 29:17 30:7 31:30 32:20 33:10
根据 q - p 的值在上表中选出m(注意p-q <0或>32的情况)
有了关键数据m,我们就可以开始计算出下一次重合的天数
(输入数据中给出的b的天数) - ((m - 1) * 23 + p) * 28 + 21252 - (输入数据中给出的d的天数)
其中,21252为三个高峰重合的周期,有23*28*33求得(注意结果为 <=0或 >21252的情况要修正)。

以下是Java代码:

/**Author:Founder Watts *作者原创,转载请注明出处 */import java.util.ArrayList;import java.util.Scanner;public class Main {    public static void main(String[] args){        Scanner input = new Scanner(System.in);        int a,b,c,d;        ArrayList<Integer> answer = new ArrayList();        while((a = input.nextInt())!=-1){            b = input.nextInt();            c = input.nextInt();            d = input.nextInt();            answer.add(caculate(a,b,c,d));        }        for(int i = 0 ; i < answer.size(); ++i){            System.out.println("Case " + (i + 1) +": the next triple peak occurs in " + answer.get(i) + " days.");        }    }    public static int caculate(int a,int b,int c,int d){        int[] mData = new int[]{1,24,14,4,27,17,7,30,20,10,33,23,13,3,26,16,6,29,19,9,32,22,12,2,25,15,5,28,18,8,31,21,11};        if(a > b)            a -= ((a - b) / 23 + 1) * 23;        if(b > c) c += ((b - c) / 33 + 1) * 33;        int p = getPFromAandB(a,b);        int q = getQFromBandC(b,c);        if(q < p) q += ((p - q) / 33 + 1) * 33;        int m = mData[(q - p) % 33];        int answer = b - ((m - 1) * 23 + p) * 28 + 21252 - d;        if(answer <= 0) answer += ((0 - answer) / 21252  + 1) * 21252;        if(answer > 21252) answer %= 21252;        return answer;    }    public static int getPFromAandB(int a,int b){        int answer = -1;        int cha = b - a;        switch(cha%5){        case 0:            answer =  cha / 5;            break;        case 1:            answer = (cha - 1) / 5 + 14;            break;        case 2:            answer = (cha - 2) / 5 + 5;            break;        case 3:            answer = (cha - 3) / 5 + 19;            break;        case 4:            answer = (cha - 4) / 5 + 10;            break;        }        return answer;    }    public static int getQFromBandC(int b,int c){        int answer = -1;        int cha = c - b;        switch(cha%5){        case 0:            answer =  cha / 5;            break;        case 1:            answer = (cha - 1) / 5 + 20;            break;        case 2:            answer = (cha - 2) / 5 + 7;            break;        case 3:            answer = (cha - 3) / 5 + 27;            break;        case 4:            answer = (cha - 4) / 5 + 14;            break;        }        return answer;    }}
0 0
原创粉丝点击