Problem 11

歐拉項目

問題11:Largest product in a grid

In the 20×20 grid below, four numbers along a diagonal line have been marked in red.

08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80
24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50
32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70
67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21
24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72
21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48

The product of these numbers is 26 × 63 × 78 × 14 = 1788696.

What is the greatest product of four adjacent numbers in the same direction (up, down, left, right, or diagonally) in the 20×20 grid?


分析

這道題目是要求找到最大的連續四個數乘積(在上,下,左,右,斜線方向),可以看出這個滿足Dynamic Programming的兩個特徵,所以可以優化查找過程而不是遍歷每一種可能。
方法是依次遍歷每個數,以這個數作爲頂點,依次計算下,右,左下斜線,右下斜線的乘積,得到這個頂點的最大乘積,然後與最大數比較。

解決方案(Java)

package Problem11;

public class LargestProduct {
                               
    private static final int[] array = {8,02,22,97,38,15,00,40,00,75,04,05,07,78,52,12,50,77,91,8
                                ,49,49,99,40,17,81,18,57,60,87,17,40,98,43,69,48,04,56,62,00
                                ,81,49,31,73,55,79,14,29,93,71,40,67,53,88,30,03,49,13,36,65
                                ,52,70,95,23,04,60,11,42,69,24,68,56,01,32,56,71,37,02,36,91
                                ,22,31,16,71,51,67,63,89,41,92,36,54,22,40,40,28,66,33,13,80
                                ,24,47,32,60,99,03,45,02,44,75,33,53,78,36,84,20,35,17,12,50
                                ,32,98,81,28,64,23,67,10,26,38,40,67,59,54,70,66,18,38,64,70
                                ,67,26,20,68,02,62,12,20,95,63,94,39,63,8,40,91,66,49,94,21
                                ,24,55,58,05,66,73,99,26,97,17,78,78,96,83,14,88,34,89,63,72
                                ,21,36,23,9,75,00,76,44,20,45,35,14,00,61,33,97,34,31,33,95
                                ,78,17,53,28,22,75,31,67,15,94,03,80,04,62,16,14,9,53,56,92
                                ,16,39,05,42,96,35,31,47,55,58,88,24,00,17,54,24,36,29,85,57
                                ,86,56,00,48,35,71,89,07,05,44,44,37,44,60,21,58,51,54,17,58
                                ,19,80,81,68,05,94,47,69,28,73,92,13,86,52,17,77,04,89,55,40
                                ,04,52,8,83,97,35,99,16,07,97,57,32,16,26,26,79,33,27,98,66
                                ,88,36,68,87,57,62,20,72,03,46,33,67,46,55,12,32,63,93,53,69
                                ,04,42,16,73,38,25,39,11,24,94,72,18,8,46,29,32,40,62,76,36
                                ,20,69,36,41,72,30,23,88,34,62,99,69,82,67,59,85,74,04,36,16
                                ,20,73,35,29,78,31,90,01,74,31,49,71,48,86,81,16,23,57,05,54
                                ,01,70,54,71,83,51,54,69,16,92,33,48,61,43,52,01,89,19,67,48};
    
    private static final int level = 20;   
    
    private int maxProduct = 0;
    
    public static void main(String[] args){        
        
        LargestProduct lp = new LargestProduct();
        
        long startTime = System.currentTimeMillis();        
        lp.compute();        
        long endTime = System.currentTimeMillis();       
        System.out.println("Time: "+(endTime-startTime));   
        
        lp.print();        
        
    }
    
    private void compute(){
        
        for(int i=0;i<array.length;i++){
            
            int rightProduct = 0;
            int downProduct = 0;
            int rightdownDiagonallyProduct = 0;
            int leftdownDiagonallyProduct = 0;
            
            int posX = i%level;
            int posY = i/level;
            
            int remainX = level - posX;
            int remainY = level - posY;            
            
            int second;
            int third;
            int fourth;
            if(remainX >3){
                second = array[i+1];
                third = array[i+2];
                fourth = array[i+3];
                rightProduct = second*third*fourth;
            }
            
            if(remainY >3){
                second = array[(posY+1)*level+posX];
                third = array[(posY+2)*level+posX];
                fourth = array[(posY+3)*level+posX];   
                downProduct = second*third*fourth;
            }
            
            if(remainX >3 && remainY >3){
                second = array[(posY+1)*level+posX+1];
                third = array[(posY+2)*level+posX+2];
                fourth = array[(posY+3)*level+posX+3]; 
                rightdownDiagonallyProduct = second*third*fourth;                
            }
            
            if(posX>=3&&remainY > 3){
                second = array[(posY+1)*level+posX-1];
                third = array[(posY+2)*level+posX-2];
                fourth = array[(posY+3)*level+posX-3];     
                leftdownDiagonallyProduct = second*third*fourth;    
            }
            
            int tmpProduct = rightProduct;
            if(downProduct>rightProduct){
                tmpProduct = downProduct;
            }
            
            if(rightdownDiagonallyProduct>tmpProduct){
                tmpProduct = rightdownDiagonallyProduct;
            }      
            
            if(leftdownDiagonallyProduct>tmpProduct){
                tmpProduct = leftdownDiagonallyProduct;
            }  
            
            if(tmpProduct>0){
                tmpProduct = array[i] * tmpProduct;
                if(tmpProduct > maxProduct){
                    maxProduct = tmpProduct;
                }
            }
            
        }
    }

    private void print(){
        System.out.println("The max product is :"+maxProduct);
    }
}



結果

Time: 0~1ms (3.40GHz雙核 8G內存)
The max product is :70600674

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章