363. 矩形区域不超过 K 的最大数值和
第一道昨天做的
我直接暴力求的,没有去进行进一步有优化,有机会再去研究吧,用到的是二维前缀和的思想,就不多说了。
class Solution {
public:
int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {
//能优化 状态不好 不想做了 以后再说
int m=matrix.size(),n=matrix[0].size();
int sum[m+1][n+1];
sum[0][0]=0;
for(int i=0;i<n+1;i++)sum[0][i]=0;
for(int j=0;j<m+1;j++)sum[j][0]=0;
for(int i=1;i<m+1;i++)
{
for(int j=1;j<n+1;j++)
{
//cout<<i<<' '<<j<<endl;
sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+matrix[i-1][j-1];
//cout<<sum[i][j]<<' ';
}
//cout<<endl;
}
int res=INT_MIN;
for(int ui=0;ui<m;ui++)
for(int uj=0;uj<n;uj++)
for(int di=ui;di<m;di++)
for(int dj=uj;dj<n;dj++)
{
int sub_sum = sum[di+1][dj+1]-sum[di+1][uj]-sum[ui][dj+1]+sum[ui][uj];
//cout<<ui<<' '<<uj<<' '<<di<<' '<<dj<<' '<<sub_sum<<endl;
if(sub_sum <= k && sub_sum > res)
{
res = sub_sum;
}
}
return res;
}
};
368. 最大整除子集
自力更生动态规划第二集,希望继续保持。。。
这题我一开始思路的暴力搜索,枚举所有的情况,结果超时了,后来意识到可以动态规划。暴力搜没啥好说的
class Solution {
public:
vector<int> res;
vector<int> tmp;
vector<int> largestDivisibleSubset(vector<int>& nums) {
sort(nums.begin(),nums.end());
for(int i=0;i<nums.size();i++)
dfs(nums,i);
return res;
}
void dfs(vector<int>& nums,int idx)
{
if(idx > nums.size())
{
if(tmp.size()>res.size())
{
res = tmp;
}
return;
}
int top = tmp.size()==0?1:tmp[tmp.size()-1];
bool pan=false;
for(int i=idx;i<nums.size();i++)
{
if(nums[i]%top == 0)
{
pan = true;
tmp.push_back(nums[i]);
dfs(nums,i+1);
tmp.pop_back();
}
}
if(pan == false)
{
if(tmp.size()>res.size())
{
res = tmp;
}
return;
}
}
};
还是详细讲讲动态规划的思路吧,其实做的还是挺艰难的,什么时候提升到中等能很快的一次过就好了。。。
整除有一个传递的特性,因此对于一个整除子集,只要某一个数能够整除这个子集里最大的一个数,那么就可以把这个数放进整除子集里,基于这种想法,我们先对数组排个序,然后从头到尾遍历。
首先当然是子问题和状态转移方程,这里的子问题不同于常规的那种,它加了一个条件:dp[i]代表以nums[i-1]为结尾的[0,i-1]区间的最大整除子集的大小,那么dp[0]=0,为了计算,我们保存一个top数组,代表dp[i]代表的最大整除子集的最大的元素,这样的话就有状态转移方程了:
dp[i] = max(dp[j])(0<=j<=i-1&&nums[i-1]%top[j]==0)
这让就能求出最大长度了,只要再加一个back_up数组,保存dp的变化轨迹,就能够回溯出结果数组了。
class Solution {
public:
vector<int> res;
vector<int> largestDivisibleSubset(vector<int>& nums) {
sort(nums.begin(),nums.end());
vector<int> top(nums.size()+1);
vector<int> dp(nums.size()+1);
vector<int> back_up(nums.size()+1);
dp[0]=0;
back_up[0]=-1;
top[0]=1;
for(int i=1;i<dp.size();i++)
{
dp[i] = -1;
for(int j=0;j<i;j++)
{
//cout<<i<<' '<<j<<endl;
if(dp[j]>=dp[i] && nums[i-1]%top[j] == 0)
{
dp[i] = dp[j];
back_up[i] = j;
top[i] = nums[i-1];
}
}
dp[i]++;
}
/*for(int i=0;i<dp.size();i++)
cout<<dp[i]<<' ';
cout<<endl;
for(int i=0;i<dp.size();i++)
cout<<back_up[i]<<' ';
cout<<endl;
for(int i=0;i<dp.size();i++)
cout<<top[i]<<' ';
cout<<endl;*/
int end = 0;
for(int i=0;i<dp.size();i++)
{
if(dp[i] > dp[end])
{
end = i;
}
}
int start = end;
while(start!=0)
{
//cout<<start<<' ';
res.push_back(nums[start-1]);
start = back_up[start];
}
reverse(res.begin(),res.end());
return res;
}
};