• 普林斯顿算法课Part2第二周作业_SeamCarving


    作业地址:http://coursera.cs.princeton.edu/algs4/assignments/seamCarving.html

    作业难点:

    1、如何获取图形的RGB属性?

      需要研习下Picture、Color类等,使用getRGB()、getRed()、getGreen()、getBlue()等函数;

    2、如何计算从顶端到底部的最低energy曲线(即最短路径)?

      使用课上讲的Dijkstra算法求解即可;

    3、是否将findHorizontalSeam和findVerticalSeam的方法合并?

      如果要合并,关键的问题在于将energy矩阵转置;

    容易扣分点:

    1、怎么确保对象内存使用在要求的内存范围内?

      不同于第一份的作业,第二部分的作业的数据结构没有显示给出。本次作业中,为了降低对象的内存使用情况,要尽量避免使用全局性的私有变量,因此部分函数的参数会变得很长;

    2、removeHorizontalSeam和removeVerticalSeam函数执行后对象未及时更新。

      要确保在两个函数的最后进行图像更新;

    部分代码:

    1、数据结构:

        private int[][] colorRGB;
        private int width;
        private int height;         
        private Picture picture;
        private static final double MAX_ENERGY = 1000.0;

    2、求解最短路径:

       private void DijkstraSP(boolean isVertical, double[][] energy, double[] distTo, int[] edgeTo) {
           int V = width * height;  
           for (int v = 0; v < V; v++) {
               distTo[v] = Double.POSITIVE_INFINITY;
               edgeTo[v] = 0;
           }
           int initLen = width;
           if (!isVertical) initLen = height;
           IndexMinPQ<Double> pq = new IndexMinPQ<Double>(V);       
           for (int v = 0; v < initLen; v++) {
               distTo[v] = MAX_ENERGY;
               pq.insert(v, distTo[v]);
           }
           boolean notFinStat = true;
           while (!pq.isEmpty() && notFinStat) { 
               relax(pq.delMin(), isVertical, energy, distTo, edgeTo, pq);           
               for (int i = V - 1; i > V - initLen; i--) 
                   if (distTo[i] != Double.POSITIVE_INFINITY) {
                       notFinStat = false;
                       break;
                   }
           }
       }   
       private void relax(int v, boolean isVertical, double[][] energy, double[] distTo, int[] edgeTo, IndexMinPQ<Double> pq) {
           int x, y, w;
           double weight;
           int seamWidth = width, seamHeight = height;  
           if (!isVertical) {
               seamWidth = height; 
               seamHeight = width;
           }
           x = v % seamWidth; 
           y = v / seamWidth;
           if (x == 0 || x == seamWidth -1 || y == seamHeight - 1) 
               return;    
           for (int delta = -1; delta < 2; delta++) {     
               w = (y+1) * seamWidth + (x + delta);
               weight = energy[x + delta][y + 1];      
               if (distTo[w] > distTo[v] + weight) {
                   distTo[w] = distTo[v] + weight;
                   edgeTo[w] = v;
                   if(y + 1 == seamHeight - 1) return;
                   if (pq.contains(w)) pq.changeKey(w, distTo[w]);
                   else pq.insert(w, distTo[w]);
               }
           }    
       }
    View Code

    3、求解顶端到底部的路径:

       private int[] findSeam(boolean isVertical, double[] distTo, int[] edgeTo) {
           int minIndex = 0;       
           double minDist = Double.POSITIVE_INFINITY;
           int seamWidth = width, seamHeight = height;
           if (!isVertical) {     
               seamWidth = height;
               seamHeight = width;
           }
           int[] seamPath = new int [seamHeight];
           for (int i = 0; i < seamWidth; i++)      
               if (distTo[(seamHeight - 1) * seamWidth + i] < minDist) {
               minIndex = (seamHeight - 1) * seamWidth + i;
               minDist = distTo[(seamHeight -1) * seamWidth + i];
           }    
           for (int i = seamHeight - 1; i > 0 ; i--) {
               seamPath[i] = minIndex % seamWidth;
               minIndex = edgeTo[minIndex];
           }
           if (seamPath.length > 1) seamPath[0] = seamPath[1];
           return seamPath;
       }   
    View Code

    4、energy转置:

       private double[][] energyTranspose(int W, int H, boolean isTranspose) {
           double[][] result = new double[W][H];
           for (int y = 0; y < H; y++)
               for (int x = 0; x < W; x++) {
               if (isTranspose) result[x][y] = energy(y, x);
               else result[x][y] = energy(x, y);
           }   
           return result;        
       }   
    View Code

    5、removeVerticalSeam():

       public void removeVerticalSeam(int[] seam) {
           if (seam.length != height || width <= 1) 
               throw new java.lang.IllegalArgumentException();
           checkSeam(seam, width);
           int[][] copy = new int[width-1][height];
           for (int y = 0; y < height; y++) {
               for (int x = 0; x < width; x++) {
                   if (x < seam[y]) copy[x][y] = colorRGB[x][y];
                   else if (x > seam[y]) copy[x-1][y] = colorRGB[x][y];
               }
           }
           width--;
           colorRGB = copy;  
           picture();
       } 
    View Code

      

  • 相关阅读:
    [转]学习B站动态转发抽奖脚本
    【LeetCode】236. 二叉树的最近公共祖先
    Java中邮件的发送
    最长递增子序列(LIS)
    最长公共子序列(LCS)
    【LeetCode】69. x 的平方根
    Lombok的使用
    Centos 中文乱码解决方法
    FWT,FST入门
    [UOJ310][UNR #2]黎明前的巧克力
  • 原文地址:https://www.cnblogs.com/notTao/p/6357337.html
Copyright © 2020-2023  润新知