2022 年度杭州未来科技城数字经济人才编程大赛
原创
©著作权归作者所有:来自51CTO博客作者mb60c9b4c3db1e6的原创作品,请联系作者获取转载授权,否则将追究法律责任
2022 年度杭州未来科技城数字经济人才编程大赛
机会总是留给有准备的人!继续加油吧少年!
zj-future01. 信号接收
思路:
定义一个指向第一个接受信号源的末尾的指针,如果后面其余的信号源的起始位置在指针的前面,那就说明有重叠的部分,因此肯定在某一个时间段接受的不是一个信号源。若后面的信号源起始位置在指针的后面,则吧指针重新赋值为该信号源的末尾位置。
最重要得按照起始位置进行排序。
class Solution {
static bool cmp(const vector<int> &a,const vector<int> &b){
return a[0]<b[0];
}
public:
bool canReceiveAllSignals(vector<vector<int>>& intervals) {
if(intervals.empty())return true;
// if(intervals.isempty())return true;
sort(intervals.begin(),intervals.end(),cmp);
bool flag=true;
int end=intervals[0][1];
for(int i=1;i<intervals.size();i++){
if(intervals[i][0]<end){
flag=false;
break;
}
end=intervals[i][1];
}
return flag;
}
};
zj-future02. 黑白棋游戏
思路:
通过滑动窗口的思想。
观察例子可以看到,最后所有的1都会在一起,窗口的大小为1的个数之和。
我们通过窗口内,如果1的个数最多,0的个数最小,那么此时需要交换的次数就是最少的。也就是交换次数==窗口大小-窗口内1的个数。
class Solution {
public:
int minSwaps(vector<int>& chess) {
int n=chess.size();
//窗口的大小
int widowSize=0;
for(int i=0;i<n;i++){
//1的个数之和即为窗口大小
widowSize+=chess[i];
}
//统计窗口内部1的个数
int widowsCount=0;
//首先先看第一个窗口的1个数
for(int i=0;i<widowSize;i++){
widowsCount+=chess[i];
}
//最少的交换次数
int minimumSwaps = widowSize - widowsCount;
//然后进行窗口的滑动
for(int i=widowSize;i<n;i++){
//记录窗口的起始位置,和结束为止
int pre=chess[i-widowSize];
int cur=chess[i];
//去除前面一个,加上后面一个进行窗口的滑动效果
widowsCount-=pre;
widowsCount+=cur;
minimumSwaps=min(minimumSwaps,widowSize-widowsCount);
}
return minimumSwaps;
}
};
zj-future03. 快递中转站选址
思路:
首先第一步肯定想到先定义一个曼哈顿函数。
其次,找到所有快递分发点的位置坐标(曼哈顿函数就是要和这些分发点进行计算)
然后通过遍历列表中的每一个节点与所有快递分发点的曼哈顿值的和。
在列表节点中找到一个最小的曼哈顿和即可。
class Solution {
public:
//定义曼哈顿函数
int manhadun(int p1x,int p1y,int p2x,int p2y){
//|p2.x - p1.x| + |p2.y - p1.y|
return (abs(p2x-p1x) +abs(p2y-p1y));
}
int buildTransferStation(vector<vector<int>>& area) {
int minDis=1000000;
int n=0;
int cnt=0;
vector<int> disX;
vector<int> disY;
//统计快递分发点的个数以及将位置信息存入(因为位置坐标是成对出现的,可以利用此来简化一些东西)
for(int i=0;i<area.size();i++){
for(int j=0;j<area[0].size();j++){
if(area[i][j]==1){
n++;
disX.push_back(i);
disY.push_back(j);
}
}
}
int temp=0;
for(int i=0;i<area.size();i++){
for(int j=0;j<area[0].size();j++){
//在某一个位置计算到所有快递分发点的曼哈顿之和
for(int q=0;q<n;q++){
temp+=manhadun(i,j,disX[q],disY[q]);
}
//寻找最小的曼哈顿之和
if(temp<minDis){
minDis=temp;
}
temp=0;
}
}
return minDis;
}
};
zj-future04. 门店商品调配
思路:
参考灵佬解析
https://leetcode.cn/circle/discuss/3p5v9B/?utm_campaign=contest_2022_zjfuture&utm_medium=leetcode_contest_eventpage&utm_source=contest&gio_link_id=qPk5jlw9
class Solution {
public:
int minTransfers(vector<vector<int>> &distributions) {
const int n = 12, m = 1 << n;
int cnt[n] = {};
for (auto &d: distributions) {
cnt[d[0]] -= d[2];
cnt[d[1]] += d[2];
}
int f[m] = {};
for (int i = 1; i < m; ++i) {
int sum = 0;
for (int j = 0; j < n; ++j)
if (i >> j & 1) sum += cnt[j];
if (sum) f[i] = INT_MAX / 2; // 防止溢出
else {
f[i] = __builtin_popcount(i) - 1;
for (int j = (i - 1) & i; j > 0; j = (j - 1) & i)
f[i] = min(f[i], f[j] + f[i ^ j]);
}
}
return f[m - 1];
}
};
总结:通过最近一个星期左右的刷题,明显感觉到是有点用的,不管是在编程思路还是说在代码编写过程中的c++stl库的运用都得到了明显的提高。也希望后面能够坚持下来,系统性的刷题。
另外:对于本次周赛,相对来说还是比较友好的,虽然只AC了两道题,那个黑白棋的问题没有想到思路,滑动窗口这一块没有了解。赛后有去学习和了解相关的知识和题目。最后一题的话,对我来说难度有点大。慢慢来,争取以后可以AC出来!!