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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了普林斯顿算法课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

  

以上是关于普林斯顿算法课Part2第二周作业_SeamCarving的主要内容,如果未能解决你的问题,请参考以下文章

第二周作业__三次锁定

第二周作业__增删改查

第二周的作业第二题_张东明

普林斯顿公开课 算法1-2:观察

程序语言与编程实践5-; Java实操2 | 第二周作业及思路讲解 | 基础知识强化考察

普林斯顿公开课 算法2-2:选择排序