比赛链接:LeetCode第 224 场周赛
第一题:可以形成最大正方形的矩形数目
思路:
根据题意简单模拟即可。
代码:
class Solution {
public:
int countGoodRectangles(vector<vector<int>>& rectangles) {
vector<int> ans;
int maxx = -1;
for(int i=0;i<rectangles.size();i++){
int x = min(rectangles[i][0],rectangles[i][1]);
ans.push_back(x);
}
for(int i=0;i<ans.size();i++){
maxx=max(maxx,ans[i]);
}
int res=0;
for(int i=0;i<ans.size();i++){
if(ans[i]==maxx) res++;
}
return res;
}
};
第二题:同积元组
思路:
如果能够找到4个数a,b,c,d使得 a
×
\times
×d = b
×
\times
×c 那么这四个数可以组成8种满足题目条件的元组。
做法就是计算出nums中所有两数乘积的值对应的个数,并用map进行存储。例如2,3,4,6这四个数中2 × \times × 6 = 12,3 × \times × 4 = 12,所以12对应的个数为2,即map[12]=2。
只有当某个数对应的map值大于等于2才满足题目的要求,设某个数对应的map值为cnt(即某个值可以由cnt对数字相乘得到),那么这个数能提供的元组数为 c n t ∗ ( c n t − 1 ) 2 \frac{cnt*(cnt-1)}{2} 2cnt∗(cnt−1) × \times × 8。
代码:
const int maxn=1e4+10;
class Solution {
public:
int tupleSameProduct(vector<int>& nums) {
int ans=0;
if(nums.size()<4) return 0;
map<int,int> mp;
for(int i=0;i<nums.size()-1;i++){
for(int j=i+1;j<nums.size();j++){
mp[nums[i]*nums[j]]++;
}
}
map<int, int>::iterator iter;
for(iter=mp.begin();iter!=mp.end();iter++){
if(iter->second>=2){
ans+=(((1+iter->second-1)*(iter->second-1))/2)*8;
}
}
return ans;
}
};
第三题: 重新排列后的最大子矩阵
思路:
枚举矩阵中的每一行作为子矩阵的第一行时所形成最大矩阵的面积。因为矩阵中列的顺序可以随意互换的,所以在枚举每一行时默认这一行中所以值为1的列都会并到一起。
对每一行进行枚举,首先找出这一行中所有值为1的列,这一行中值为1的列组成的是子矩阵的长,然后用 n u m num num数组记录这一行中值为1的列从当前行开始往下1的个数(包括当前行), n u m num num数组记录的值即为子矩阵所能达到的高。
当前行作为子矩阵的第一行所能形成的矩阵的最大面积为 n u m [ i ] ∗ x num[i]*x num[i]∗x,其中 x x x是这一行中 n u m num num值大于等于 n u m [ i ] num[i] num[i]的列的个数。
最后枚举每个当前行中值为1的列,每次求最值 a n s = m a x ( a n s , n u m [ i ] ∗ x ) ans=max(ans,num[i] *x) ans=max(ans,num[i]∗x)
如果枚举的当前一整行和矩阵的最后一整行所围成的矩阵面积小于等于 a n s ans ans时,就结束程序,这时已经没有继续计算的必要, 否则在全1的测试样例中会TLE。
代码:
class Solution {
public:
int largestSubmatrix(vector<vector<int>>& matrix) {
int ans=0;
int colnum=matrix[0].size(),rownum=matrix.size();
for(int i=0;i<rownum;i++){
if((rownum-i)*colnum<=ans) break;
vector<int> pos;
vector<int> num;
for(int j=0;j<colnum;j++){
if(matrix[i][j]==1){
pos.push_back(j);
}
}
for(int j=0;j<pos.size();j++){
int x=0;
for(int k=i;k<rownum;k++){
if(matrix[k][pos[j]]==1) x++;
else break;
}
num.push_back(x);
}
sort(num.begin(),num.end());
int x = num.size();
for(int j=0;j<num.size();j++){
ans=max(ans,num[j]*(x-j));
}
}
return ans;
}
};
第四题:猫和老鼠 II
思路:
运用记忆化搜索的方法,维护数组
d
p
[
i
s
M
o
u
s
e
]
[
i
d
x
]
[
r
o
u
n
d
]
dp[isMouse][idx][round]
dp[isMouse][idx][round]表示在该状态下先移动的玩家是否可以赢得游戏。其中:
- i s M o u s e isMouse isMouse等于1时表示老鼠,等于0时表示猫。
- i d x idx idx 是一个 [0,4096)之间的整数,代表了当前猫和老鼠的位置。
- r o u n d round round 代表当前的游戏轮数。根据题意, r o u n d ≤ 1000 round≤1000 round≤1000。不过实际上还可以更优,实际上不会超过 m a x R o u n d = 8 × 8 maxRound = 8 \times 8 maxRound=8×8(即格子大小)
运用search函数进行递归搜索,直到搜索到满足游戏结束的特殊情况,否则继续搜索。
具体的题解可以看大佬博客:【记忆化搜索】思路简单,比较暴力
代码:
class Solution {
public:
int h,w;
pair<int,int> food;
vector<vector<vector<int>>> dp;
vector<string> g;
int cj,mj;
int maxn;
int encode(pair<int,int>& cat, pair<int,int>& mouse){
int ci = cat.first * w + cat.second;
int mi = mouse.first * w + mouse.second;
return ci * h * w + mi;
}
int search(pair<int,int> cat, pair<int,int> mouse,int round, int isMouse){
if(round == maxn + 1) return 0;
if(isMouse == 1 && g[mouse.first][mouse.second] == 'F') return 1;
if(isMouse == 0 && g[cat.first][cat.second] == 'F') return 1;
if(isMouse == 1 && cat.first == mouse.first && cat.second == mouse.second) return 0;
if(isMouse == 0 && cat.first == mouse.first && cat.second == mouse.second) return 1;
int idx = encode(cat,mouse);
if(dp[isMouse][idx][round] >= 0) return dp[isMouse][idx][round];
int ret = 0;
vector<pair<int,int>> directions{{0,1},{0,-1},{1,0},{-1,0}};
if(isMouse == 1){
if(search(cat,mouse,round,0) == 0)
ret = 1;
else{
for(const auto [di,dj]:directions){
for(int jump = 1; jump <= mj; jump++){
int ni = mouse.first + jump * di;
int nj = mouse.second + jump * dj;
if(ni < 0 || ni >=h || nj < 0 || nj >= w) break;
if(g[ni][nj] == '#') break;
if(search(cat,make_pair(ni,nj),round,0) == 0){
ret = 1;
break;
}
}
if(ret == 1) break;
}
}
}
else{
int nextRound = round + 1;
if(search(cat, mouse, round + 1, 1) == 0)
ret = 1;
else{
for (const auto [di, dj]: directions) {
for (int jump = 1; jump <= cj; jump++) {
int ni = cat.first + jump * di;
int nj = cat.second + jump * dj;
if (ni < 0 || ni >= h || nj < 0 || nj >= w) {
break;
}
if (g[ni][nj] == '#') {
break;
}
if (search(make_pair(ni, nj), mouse, round + 1, 1) == 0) {
ret = 1;
break;
}
}
if (ret == 1) {
break;
}
}
}
}
dp[isMouse][idx][round] = ret;
return ret;
}
bool canMouseWin(vector<string>& grid, int catJump, int mouseJump) {
h = grid.size();
w = grid[0].size();
maxn = h * w + 2;
cj = catJump;
mj = mouseJump;
g = grid;
dp = vector<vector<vector<int>>>(2, vector<vector<int>>(h * w * h * w, vector<int>(maxn + 1, -1)));
pair<int,int> cat,mouse;
for(int i = 0; i < h; i++){
for(int j = 0; j < w; j++){
if(g[i][j] == 'M') mouse = make_pair(i, j);
else if(g[i][j] == 'C') cat = make_pair(i, j);
}
}
int ans = search(cat, mouse, 0, 1);
return ans == 1? true:false;
}
};