1. 程式人生 > >CS106B Section Solutions #4

CS106B Section Solutions #4

Problem 1: Filling a Region

回溯思想填空白

#include <iostream>
#include "vector.h"
#include "grid.h"
using namespace std;

enum pixelStateT { White, Black };
struct pointT {
    int row, col;
};

void FillReign(pointT pt, Grid<pixelStateT> & screen);
bool IsOffGrid(pointT pt, Grid<pixelStateT> & grid);
pointT move(pointT pt, int i);

int main() {
    //建立圖
    Grid<pixelStateT> screen(10,10);
    for(int i=0;i<10; i++) screen(0,i) = Black;
    for(int i=0;i<10; i++) screen(1,i) = White;
    for(int i=0;i<10; i++) screen(2,i) = Black;
    for(int i=0;i<10; i++) screen(3,i) = White;
    for(int i=0;i<10; i++) screen(4,i) = Black;
    for(int i=0;i<10; i++) screen(5,i) = White;
    for(int i=0;i<10; i++) screen(6,i) = Black;
    for(int i=0;i<10; i++) screen(7,i) = White;
    for(int i=0;i<10; i++) screen(8,i) = Black;
    for(int i=0;i<10; i++) screen(9,i) = White;

    //列印圖
    for(int i=0; i<10; i++){
        cout<< screen(i,0)<<screen(i,1)<<screen(i,2)<<screen(i,3) <<screen(i,4)
            <<screen(i,5)<<screen(i,6)<<screen(i,7)<<screen(i,8)<<screen(i,9)<<endl;
        }
    //選擇點
    cout <<"-------------"<<endl;
    pointT pt;
    pt.row = 7;
    pt.col = 4;
    //填充
    FillReign(pt, screen);
    //列印新圖
    for(int j=0; j<10; j++){
        cout<< screen(j,0)<<screen(j,1)<<screen(j,2)<<screen(j,3) <<screen(j,4)
            <<screen(j,5)<<screen(j,6)<<screen(j,7)<<screen(j,8)<<screen(j,9)<<endl;
    }
    return 0;
}

void FillReign(pointT pt, Grid<pixelStateT> & screen){
    if (IsOffGrid(pt,screen))
        return;
    if (screen(pt.row, pt.col) == Black)
        return;
    screen(pt.row, pt.col) = Black;
    for(int i=0; i<4; i++) {
        FillReign(move(pt, i),screen);
    }
}

bool IsOffGrid(pointT pt, Grid<pixelStateT> & grid){
    return pt.row < 0 || pt.row >= grid.numRows() ||
           pt.col < 0 || pt.col >= grid.numCols();
}
pointT move(pointT pt, int i){
    pointT temp;
    switch(i){
        case 0: temp.row = pt.row-1; temp.col = pt.col ; break;
        case 1: temp.row = pt.row+1; temp.col = pt.col ; break;
        case 2: temp.row = pt.row; temp.col = pt.col-1 ; break;
        case 3: temp.row = pt.row; temp.col = pt.col+1 ; break;
    }
    return temp;


/*
結果展示:
point (7,4):
1111111111
0000000000
1111111111
0000000000
1111111111
0000000000
1111111111
0000000000
1111111111
0000000000
-------------
1111111111
0000000000
1111111111
0000000000
1111111111
0000000000
1111111111
1111111111
1111111111
0000000000

point (8,4):
1111111111
0000000000
1111111111
0000000000
1111111111
0000000000
1111111111
0000000000
1111111111
0000000000
-------------
1111111111
0000000000
1111111111
0000000000
1111111111
0000000000
1111111111
0000000000
1111111111
0000000000

*/

Problem 2: Shortest Path Through a Maze

由於mazesolve函式已經給出類,只需要稍微改改就行

int ShortestPathLength(pointT pt){
    int shortest, len;
    if(OutsideMaze(pt))
    {
        return 0;
    }
    if(IsMarked(pt))
    {
        return Nosolution;
    }
    shorest = NoSolution;
    MarkSquire(pt);
    for(directionT dir = North; dir <= West; dir = directionT(dir+1)){
        if(!WallExists(pt,dir))
        {
             len = ShortestPathLength(AdjacentPoint(pt, dir));
             if (len < shortest){
                 shortest = len;
                }
        }
    }
    UnmarkSquare(pt);
    if (shortest == NoSolution){
        return NoSolution;
        }
        else
        {
            return (shortest + 1);
            }
}

Problem 3: Pointers

這個指標概念問題沒什麼說得

Problem 4: Linked List Warmup

a) 兩種方法將vector改成連結串列,遞迴方法看看就好

Cell * ConvertToListIter(Vector<int> vector){
    Cell *head = new Cell;//連結串列頭用new建立
    head->next = NULL;
    head->value = vector[0];
    Cell *curr = head;//取頭指標,之前的 head用於返回
    for(int i=0;i<vector.size(); i++){
        Cell *newCell = new Cell;
        newCell->next = NULL;
        newCell->value = vector[i];
        curr->next = newCell;
        newCell = curr;
    }
    return head;
}
Cell * ConvertToListRealRecur(Vector<int> &vector, int index)
{
    if(index >= vector.size())
    return NULL;
    Cell *curr = new Cell;
    curr->value = vector[index];
    curr->next = ConvertToListRealRecur(vector, index + 1);
    return curr;
}
Cell * ConvertToListRecur(Vector<int> vector)
{
return ConvertToRealRecur(vector, 0);
}

b)連結串列操作

int SumListIter(Cell *list){
    int sum = 0;
    Cell *curr = list;//curr指向頭指標
    whlie(curr != NULl){
        sum += curr->value;
        curr = curr->next;
    }
    return sum;
}
int SumListRecur(Cell *list)
{
if(list == NULL)
return 0;
else
return list->value + SumListRecur(list->next);//連結串列遞迴經典操作
}

Problem 5: Linked List Trace

實現的功能就是把連結串列最後一個提到第一個,果然學指標最好的例子還是連結串列

//Link List Trave
void PopRocks(Cell * & mikey)//&傳遞,用於改變頭指標
{
Cell *ptr;
  for (ptr = mikey; ptr->next != NULL; ptr = ptr->next)//將指標傳遞到結尾
  {
    /* Note: loop body intentionally left empty */  //想不到把,空迴圈
  }
  ptr->next = mikey;//將結尾連到開頭
  ptr = ptr->next;//移到原來頭指標
  mikey = mikey->next;//把原來的第二個數變成頭指標
  ptr->next = NULL;//把原來的第一個指向空指標,即變成結尾
}

Problem 6: Append

記得以前資料結構老師講過這個例子,懷念

void Append(Cell *& first,Cell * second){
    if(first == NULl)
    {
        first = second; //這就是為什麼之前first要用&傳遞,因為當first為空時,first的頭指標會改變
    }
    else{
        Append(first->next,second);//臥槽,亮瞎有木有
    }
}