Dynamic Programming series

DP is absolutely the best way to category levels of programming..... and it is always the favourite questions being asked by FB or Google.

1: Entry Level DP problem.    

/*
  A sequence of numbers is called a zig-zag sequence if the differences between successive numbers strictly alternate between positive and negative. The first difference (if one exists) may be either positive or negative. A sequence with fewer than two elements is trivially a zig-zag sequence.

For example, 1,7,4,9,2,5 is a zig-zag sequence because the differences (6,-3,5,-7,3) are alternately positive and negative. In contrast, 1,4,7,2,5 and 1,7,4,5,5 are not zig-zag sequences, the first because its first two differences are positive and the second because its last difference is zero.

Given a sequence of integers, sequence, return the length of the longest subsequence of sequence that is a zig-zag sequence. A subsequence is obtained by deleting some number of elements (possibly zero) from the original sequence, leaving the remaining elements in their original order.
*/
#include "header.h"
using namespace std;
int longestZigzagSequence(vector<int>& nums) {
  int n = nums.size();
  vector<int> end_positive(n, 0);
  vector<int> end_negative(n, 0);
  for(int i = 0; i < nums.size(); ++i) {
    end_positive[i] = 1;
    end_negative[i] = 1;
    for(int j = 0; j <= i; ++j) {
      if(nums[j] > nums[i]) end_negative[i] = max(end_positive[j]+1, end_negative[i]);
      if(nums[i] > nums[j]) end_positive[i] = max(end_negative[j]+1, end_positive[i]);
    }
  }
  return max(end_negative[n-1], end_positive[n-1]);
}

int main(void) {
  vector<int> nums{1, 17, 5, 10, 13, 15, 10, 5, 16, 8};
  vector<int> test{ 70, 55, 13, 2, 99, 2, 80, 80, 80, 80, 100, 19, 7, 5, 5, 5, 1000, 32, 32 };
  cout << longestZigzagSequence(test) << endl;
}

// Same as rob neighbours in LeetCode 

/*
The old song declares "Go ahead and hate your neighbor", and the residents of Onetinville have taken those words to heart. Every resident hates his next-door neighbors on both sides. Nobody is willing to live farther away from the town's well than his neighbors, so the town has been arranged in a big circle around the well. Unfortunately, the town's well is in disrepair and needs to be restored. You have been hired to collect donations for the Save Our Well fund.

Each of the town's residents is willing to donate a certain amount, as specified in the int[] donations, which is listed in clockwise order around the well. However, nobody is willing to contribute to a fund to which his neighbor has also contributed. Next-door neighbors are always listed consecutively in donations, except that the first and last entries in donations are also for next-door neighbors. You must calculate and return the maximum amount of donations that can be collected.
*/
#include "header.h"
using namespace std;

int maxDonations(vector<int>& nums) {
  if(nums.size() == 0) return 0;
  int n = nums.size();
  if(n == 1) return nums[0];
  if(n == 2) return max(nums[0], nums[1]);

  vector<int> donations_odd(n, 0);
  vector<int> donations_even(n, 0);
  donations_odd[0] = nums[0];
  donations_even[1] = nums[1];
  for(int i = 2; i < n - 1; ++i) {
    donations_odd[i] = max(donations_odd[i-2] + nums[i], donations_odd[i-1]);
  }
  for(int i = 3; i < n; ++i) {
    donations_even[i] = max(donations_even[i-2] + nums[i], donations_even[i-1]);
  }
  return max(donations_even[n-1], donations_odd[n-2]);
}

int main(void) {
  vector<int> nums{94, 40, 49, 65, 21, 21, 106, 80, 92, 81, 679, 4, 61,
  6, 237, 12, 72, 74, 29, 95, 265, 35, 47, 1, 61, 397,
  52, 72, 37, 51, 1, 81, 45, 435, 7, 36, 57, 86, 81, 72};
  cout << maxDonations(nums) << endl;
}

Medium Level

Top Coder:  ChessMetric

It is very straight forward to first come up with dfs searching.

struct Pair {
  int _x;
  int _y;
  Pair(int x, int y) : _x(x), _y(y) {}
};

void waysToMove(int matrixSize, Pair start, Pair end, int steps, long long& method) {
  if(start._x < 0 || start._x >= matrixSize || start._y < 0 || start._y >= matrixSize) return;
  if(end._x < 0 || end._x >= matrixSize || end._y < 0 || end._y >= matrixSize || steps < 0) return;
  if((steps == 0) && (start._x == end._x) && (start._y == end._y)) {
    method++;
    return;
  }
  waysToMove(matrixSize, Pair(start._x - 1, start._y), end, steps - 1, method);
  waysToMove(matrixSize, Pair(start._x + 1, start._y), end, steps - 1, method);
  waysToMove(matrixSize, Pair(start._x, start._y + 1), end, steps - 1, method);
  waysToMove(matrixSize, Pair(start._x, start._y - 1), end, steps - 1, method);

  waysToMove(matrixSize, Pair(start._x + 1, start._y + 1), end, steps - 1, method);
  waysToMove(matrixSize, Pair(start._x + 1, start._y - 1), end, steps - 1, method);
  waysToMove(matrixSize, Pair(start._x - 1, start._y - 1), end, steps - 1, method);
  waysToMove(matrixSize, Pair(start._x - 1, start._y + 1), end, steps - 1, method);

  waysToMove(matrixSize, Pair(start._x - 1, start._y + 2), end, steps - 1, method);
  waysToMove(matrixSize, Pair(start._x - 1, start._y - 2), end, steps - 1, method);
  waysToMove(matrixSize, Pair(start._x + 1, start._y - 2), end, steps - 1, method);
  waysToMove(matrixSize, Pair(start._x + 1, start._y + 2), end, steps - 1, method);

  waysToMove(matrixSize, Pair(start._x - 2, start._y - 1), end, steps - 1, method);
  waysToMove(matrixSize, Pair(start._x - 2, start._y + 1), end, steps - 1, method);
  waysToMove(matrixSize, Pair(start._x + 2, start._y - 1), end, steps - 1, method);
  waysToMove(matrixSize, Pair(start._x + 2, start._y + 1), end, steps - 1, method);
}


Apparently, we can just use DP to solve it.

class ChessMetric {
public:
	long long howMany( int size, vector <int> start, vector <int> end, int numMoves ) {
		this->size = size;
		map[0][start[0]][start[1]] = 1;

		for(int mv = 1; mv <= numMoves; ++mv) {
			for(int i = 0; i < size; ++i) {
				for(int j = 0; j < size; ++j) {
					map[mv][i][j] = neigh_sum(mv-1,i,j);
				}
			}
		}
		return map[numMoves][end[0]][end[1]];
	}
private:
	int size;
	const vector<pair<int,int>> ds = {{ 0, 1}, { 1, 0}, { 0,-1}, {-1, 0},
					  { 1, 1}, {-1, 1}, { 1,-1}, {-1,-1}, 
					  { 1, 2}, { 2, 1}, {-1, 2}, {-2, 1},
					  { 1,-2}, { 2,-1}, {-1,-2}, {-2,-1}};
	long long neigh_sum(int mv, int i, int j) {
		long long total = 0;
		for(auto delta:ds) {
			int x = i + delta.first;
			int y = j + delta.second;
			if(inbound(x,y)) {
				total += map[mv][x][y];
			}
		}
		return total;
	}

	bool inbound(int i, int j) {
		return 0 <= i && i < size && 0 <= j && j < size;
	}
};

1: https://www.topcoder.com/community/data-science/data-science-tutorials/dynamic-programming-from-novice-to-advanced/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值