MC0116 水往低处流 码题集
这道题第一反应是对每个点进行dfs或者bfs,暴力标记所有的点,但是复杂度太高,看了题解之后,发现一种转化的方法。
遍历所有的点,当他是上下左右中最大的,其肯定是要挑一次水。
给出我的方法,老规矩,用哨兵,减少边界检查。
#include<iostream>
#include<map>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
vector<vector<int>> orgion;
int sizeOrgion;
int res = 0;
void dfs(int x,int y) {
int eight = orgion[x][y];
if (eight >= orgion[x + 1][y]
&& eight >= orgion[x][y + 1]
&& eight >= orgion[x - 1][y]
&& eight >= orgion[x][y - 1]) {
res++;
}
}
int main()
{
cin >> sizeOrgion;
sizeOrgion += 2;
orgion = vector<vector<int>>(sizeOrgion, vector<int>(sizeOrgion, 0));
for (int i = 1; i < sizeOrgion - 1; i++) {
for (int j = 1; j < sizeOrgion - 1; j++)
cin >> orgion[i][j];
}
for (int i = 1; i < sizeOrgion - 1; i++) {
for (int j = 1; j < sizeOrgion - 1; j++)
dfs(i, j);
}
cout << res << endl;
}
MC0136函数的幂Ⅱ
这种题,可以用递归试试,但会超时。主要还是数学方法的转化,求出Cn和Cn-1的关系式,循环求出题目即可。证明:
这里有个余数的结论,可以证明一下。
代码
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include<stack>
#include<set>
using namespace std;
int C, D;
int main()
{
int a, b;
cin >> a >> b >> C >> D;
a--;
while (a--) {
int C1 = C * C%10;
int D1 = D * (C + 1)%10;
C = C1;
D = D1;
}
cout << (C * b + D) % 10 << endl;
}
MC0138吃外卖
没啥好说的,记录一下优先级队列的使用。
#include<iostream>
#include<queue>
using namespace std;
int main()
{
priority_queue<int> pq;
int n, m;
cin >> n >> m;
while (m--) {
int temp;
cin >> temp;
pq.push(temp);
}
int res = 0;
while (n--) {
int temp = pq.top();
res += temp;
pq.pop();
pq.push(temp - 1);
}
cout << res << endl;
}
MC0148射线的交
最妙的地方在于
1、用正数负数表示上下 左右两类方向,后面可以通过符号判断是否相乘
2、a可能有两种方向,通过swap来保证其只有一种
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
struct Point {
int x;
int y;
int direction;
};
int getDir(char a) {
switch (a)
{
case 'U':
return 1;
case 'L':
return -1;
case 'D':
return 2;
case 'R':
return -2;
default:
break;
}
return '0';
}
int main()
{
int n; cin >> n;
vector<Point> orgion(n);
for (int i = 0; i < n; i++) {
char temp;
cin >> orgion[i].x >> orgion[i].y>>temp;
orgion[i].direction = getDir(temp);
}
int res = 0;
for (int i = 0; i < n; i++) {
for (int j = i+1; j < n; j++) {
Point a = orgion[i];
Point b = orgion[j];
if (a.direction >0)
swap(a, b);
if (a.direction * b.direction < 0) {
if (a.direction == -2 && b.x >= a.x && ((b.direction == 1 && a.y >= b.y) || (b.direction == 2 && a.y <= b.y)))
res++;
else if (a.direction == -1 && b.x <= a.x && ((b.direction == 1 && a.y >= b.y) || (b.direction == 2 && a.y <= b.y)))
res++;
}
}
}
cout << res << endl;
}
MC015023划分
有组合数学那味道了,乍一看有点懵,但是解法还是暴力枚举。
1、求出所有的钱数综合sum,2的个数cn2,3的个数cn3
2、当sum为奇数的时候,返回false
3、sum=sum / 2
4、遍历所有2的可能,当算出3的个数小于等于cn3,即可表示出一堆的方法
5、剩下的一堆就是sum/2了
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
int cn2 = 0, cn3 = 0,sumAll=0;
int n; cin >> n;
while (n--) {
int temp; cin >> temp;
(temp == 2) ? cn2++ : cn3++;
sumAll += temp;
}
if (sumAll % 2 == 1)
{
cout << "NO" << endl;
return 0;
}
sumAll /= 2;
for (int i = 0; i <= cn2; i++) {
int tempSum = sumAll - i * 2;
if (tempSum < 0)
break;
if (tempSum % 3 == 0 && tempSum / 3 <= cn3) {
cout << "YES" << endl;
return 0;
}
}
cout << "NO" << endl;
return 0;
}