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个测试案例,是因为只阅读了题目最后提示的建立班次集合,所以我按照优化的思路开始建立可行解的集合,而遗漏了另一句提示:
有两种选择:您可以给员工轮班,或者不给员工轮班。这两种选择中的一种会比另一种更好,或者它们将与产生的价值挂钩。在尝试之前,您不会知道哪一种更好,因此(递归地)探索这两种选项并报告哪一种能带来更多价值。
一个启发是,应该避免用循环的思维写递归,重点是每一次的判断与操作,寻找目标,而非搜寻所有可能性。