【CS106B】作业3 Assignment 3. Recursion!

Part One: The Sierpinski Triangle

#include "Sierpinski.h"
#include "error.h"
using namespace std;

void drawTriangle(GWindow& window,
                  double x0, double y0,
                  double x1, double y1,
                  double x2, double y2) {
    window.setColor("black");
    window.fillPolygon({ x0, y0, x1, y1, x2, y2 });
}

void drawSierpinskiTriangle(GWindow& window,
                            double x0, double y0,
                            double x1, double y1,
                            double x2, double y2,
                            int order) {
    if(order < 0)
        error("the order cannot be negative!");
    else if(order==0)
        drawTriangle(window, x0, y0, x1, y1, x2, y2);
    else{
        drawSierpinskiTriangle(window, x0, y0, (x0+x1)/2, (y0+y1)/2, (x0+x2)/2, (y0+y2)/2, order-1);
        drawSierpinskiTriangle(window, (x0+x1)/2, (y0+y1)/2, x1, y1, (x1+x2)/2, (y1+y2)/2, order-1);
        drawSierpinskiTriangle(window, (x0+x2)/2, (y0+y2)/2, (x1+x2)/2, (y1+y2)/2, x2, y2, order-1);
    }
    (void) window;
    (void) x0; (void) y0;
    (void) x1; (void) y1;
    (void) x2; (void) y2;
    (void) order;
}

Part Two: Human Pyramids

#include "HumanPyramids.h"
#include "map.h"
#include "vector.h"
#include "error.h"
using namespace std;

double weightOnBackOf_function(int row, int col, int pyramidHeight, Map<Vector<int>, int> & memoization){
    if(row<0 || col<0 || pyramidHeight<0 || row>pyramidHeight-1 || col>row)
        error("out of bound");
    Vector<int> index(2);
    int tmp;
    index[0] = row;
    index[1] = col;
    if(row==0 && col==0) return 0;
    else if((row-col)==0){
        if(memoization.containsKey(index)) return memoization.get(index);
        else tmp = weightOnBackOf_function(row-1, col-1, pyramidHeight, memoization)/2+80;
    }else if((row-col)==row){
        if(memoization.containsKey(index)) return memoization.get(index);
        else tmp = weightOnBackOf_function(row-1, col, pyramidHeight, memoization)/2+80;
    }else{
        if(memoization.containsKey(index)) return memoization.get(index);
        else tmp = weightOnBackOf_function(row-1, col, pyramidHeight, memoization)/2+weightOnBackOf_function(row-1, col-1, pyramidHeight, memoization)/2+160;
    }
    memoization.put(index, tmp);
    return tmp;
}
double weightOnBackOf(int row, int col, int pyramidHeight) {
    Map<Vector<int>, int> memoization;

    return weightOnBackOf_function(row, col, pyramidHeight, memoization);
}

Part Three: What Are YOU Doing?

#include "WhatAreYouDoing.h"
#include <cctype>
#include "strlib.h"
using namespace std;

void allEnphasesOf_func(int index, Vector<string>& token, string senteces, Set<string>& all_emphases){
    if(index==token.size()-1){
        if(isalpha(token[index][0])){
            all_emphases.add(senteces + toUpperCase(token[index]));
            all_emphases.add(senteces + toLowerCase(token[index]));
            return;
        }
        else{
            all_emphases.add(senteces + token[index]);
            return;
        }
    }
    if(isalpha(token[index][0])){
        allEnphasesOf_func(index+1, token, senteces+toUpperCase(token[index]), all_emphases);
        allEnphasesOf_func(index+1, token, senteces+toLowerCase(token[index]), all_emphases);
    }else{
        allEnphasesOf_func(index+1, token, senteces+token[index], all_emphases);
    }
}

Set<string> allEmphasesOf(const string& sentence) {
    Vector<string> token;
    token = tokenize(sentence);
    Set<string> all_emphases;
    string sentences;

    allEnphasesOf_func(0, token, sentences, all_emphases);
}

Part Four: Shift Scheduling

#include "ShiftScheduling.h"
using namespace std;
// 避免用循环的思维写递归
Set<Shift> findHighestSchedules(const Set<Shift>& shifts, const Set<Shift>& sofar, int maxHours){
    if(shifts.size()==0){
        Set<Shift> ans = {};
        ans += sofar;
        return ans;
    }  // 子集空了,没得选了,返回
    Shift elem = shifts.first();  // 从可选子集中取出一个元素
    Set<Shift> remaining = shifts-elem;  // 可选子集剩余的元素
    Set<Shift> if_choose = sofar+elem; // 如果加上这个元素,现在的时间表集合
    double sum = 0;
    bool flag = 1;  // 指示是否超时或者时间重叠的标志
    for(auto i:if_choose){sum+=lengthOf(i);}
    if(sum>maxHours){flag = 0;}  // 检查是否超时
    for(const auto& value : sofar){
        if(overlapsWith(elem, value)){
            flag = 0;
            break;
        }
    } // 检查是否重叠
    if(flag==1 && maxHours-lengthOf(elem)>=0){  // 不超时也不重叠,可以考虑要不要加这个元素
        Set<Shift> x = findHighestSchedules(remaining, if_choose, maxHours);  // 加上这个元素后的时间表
        Set<Shift> y = findHighestSchedules(remaining, sofar, maxHours);  // 不加这个元素的时间表
        int sum1 = 0 , sum2 = 0;
        for(auto p: x)sum1 +=valueOf(p);
        for(auto q: y)sum2 +=valueOf(q);
        if(sum1>=sum2) return x;
        return y;  // 哪个时间表创造的价值更大,就选择哪个
    }else{  // 超时或者重叠了,不考虑这个元素
        return findHighestSchedules(remaining, sofar, maxHours);
    }
}
Set<Shift> highestValueScheduleFor(const Set<Shift>& shifts, int maxHours) {
    /* TODO: Delete the next few lines and implement this function. */
    if(maxHours<0){
        error("maxHours cannot be negative");
    }
    Set<Shift> max_schedule = {};
    Set<Shift> one_schedule = {};
    Set<Set<Shift>> all_schedules;

    return findHighestSchedules(shifts, {}, maxHours);
}

最后一题参考了别人的答案
一开始一直卡在第12个测试案例,是因为只阅读了题目最后提示的建立班次集合,所以我按照优化的思路开始建立可行解的集合,而遗漏了另一句提示:

有两种选择:您可以给员工轮班,或者不给员工轮班。这两种选择中的一种会比另一种更好,或者它们将与产生的价值挂钩。在尝试之前,您不会知道哪一种更好,因此(递归地)探索这两种选项并报告哪一种能带来更多价值。

一个启发是,应该避免用循环的思维写递归,重点是每一次的判断与操作,寻找目标,而非搜寻所有可能性。


题目来源CS106B

  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值