- leetcode-546移除盒子
题型:动态规划
难度:困难
题目:给出一些不同颜色的盒子,盒子的颜色由数字表示,即不同的数字表示不同的颜色。你将经过若干轮操作去去掉盒子,直到所有的盒子都去掉为止。每一轮你可以移除具有相同颜色的连续 k 个盒子(k >= 1),这样一轮之后你将得到 k*k 个积分。当你将所有盒子都去掉之后,求你能获得的最大积分和。
代码:
class Solution {
public:
int dp[100][100][100];
public:
//不能只考虑连续相同的情况,因为可能会出现:[3,1,3,3,3]这种情况,就要把前面的3和后面三个连起来。
//本题用动态规划加dfs去做。
//dfs(left,right,k),表示left~right区间+的连续k个等于right对应元素
//第一种情况是right-1后面连续k+1个;dfs(left,right-1,0)+(k+1)^2
//第二种情况是right之前,存在某个位置i,有与其相同的值,可以和后面k+1个进行合并(把right之前的区间,分为两份,前面是包含这个元素+k+1个,后面区间不包含);dfs(left,i,k+1)+dfs(i+1,right-1,0)
//上面两种情况取最大值dp[left][right][k]?
int dfs(vector<int> &boxes,int left,int right,int k){
if(left > right) return 0;
if(dp[left][right][k] != 0) return dp[left][right][k];
while(left<right && boxes[right]==boxes[right-1])
{
right--;
k++;
}
//if(right>=1)
dp[left][right][k] = dfs(boxes,left,right-1,0)+(k+1)*(k+1);
for(int i=left;i<right;i++)
{
//看当前这个值,是否和right位置的值相等,相等即第二种情况。
if(boxes[i] == boxes[right])
{
dp[left][right][k] = max(dp[left][right][k],dfs(boxes,left,i,k+1)+dfs(boxes,i+1,right-1,0) );
}
}
return dp[left][right][k];
}
int removeBoxes(vector<int>& boxes) {
memset(dp,0,sizeof(dp));
int res = dfs(boxes,0,boxes.size()-1,0);
return res;
}
};
借鉴:https://leetcode-cn.com/problems/remove-boxes/solution/yi-chu-he-zi-by-leetcode-solution/
- leetcode-1007行相等的最少多米诺旋转
题型:贪心
难度:中等
题目:在一排多米诺骨牌中,A[i] 和 B[i] 分别代表第 i 个多米诺骨牌的上半部分和下半部分。(一个多米诺是两个从 1 到 6 的数字同列平铺形成的 —— 该平铺的每一半上都有一个数字。)我们可以旋转第 i 张多米诺,使得 A[i] 和 B[i] 的值交换。返回能使 A 中所有值或者 B 中所有值都相同的最小旋转次数。如果无法做到,返回 -1.
代码:
class Solution {
public:
//遍历两个数组,如果结果想要满足条件,必须保证最后在同一数组里的这个数值,总个数一定大于等于数组长度。遍历后比长度小,直接返回。满足条件,再遍历一次,选择数组中存在这个数多的,返回缺失的个数,就是最小次数了。
//注:一个多米诺是两个从 1 到 6 的数字,数值最大为6
int minDominoRotations(vector<int>& A, vector<int>& B) {
if(A.size()==0 || A.size()!=B.size()) return -1;
vector<int> nums(6,0);
for(int i=0;i<A.size();i++)
{
if(A[i] == B[i])
{
//如果这张牌两半一样,只能算作一个
nums[A[i]-1]++;
}
else
{
nums[A[i]-1]++;
nums[B[i]-1]++;
}
}
int flag = 0;
int num = 0;
for(int i=0;i<6;i++)
{
if(nums[i] >= A.size())
{
flag = 1;
num = i+1;
break;
}
}
if(flag == 0) return -1;
int count1 = 0;
int count2 = 0;
for(int i=0;i<A.size();i++)
{
if(A[i] == num) count1++;
if(B[i] == num) count2++;
}
return count1<count2?A.size()-count2:A.size()-count1;
}
};