题目链接:点击打开链接
A. Tetris
(水题)
题意:给出n列的俄罗斯方块游戏,m步操作,随后m个数表示当前一个1*1的俄罗斯方块投放在第几列,当最下面一行都有方块时会消去并且计分,问当m次操作后积分为多少?
解法:题目要求最终消去了多少行,即求m步操作在不同列投放方块的最小值即可。
代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
#define inf 0x3f3f3f3f
int a[1500];
int main()
{
int n, m, x;
cin >> n >> m;
for (int i = 0; i < m; i++)
{
cin >> x;
a[x]++;
}
int ans = inf;
for (int i = 1; i <= n; i++)
ans = min(ans, a[i]);
cout << ans << endl;
return 0;
}
B. Lecture Sleep
(水题)
题意:某学生上课容易犯困,第一行给出n,m表示n个时间段,和提神药水持续时间m秒,第二行给出n个数a[i],表示第i个时间段该同学可以记录a[i]的知识点,第三行给出n个数b[i],表示第i个时间段该同学的状态,1表示醒着,0表示睡着了(使用提神药水可以醒来)。输出该同学最多能记录多少知识点(即最优的提神药水使用时段的贪心)。
解法:即求解提神药水在各个时间点使用能获得的最大知识点值(不包含原本醒着的),再加上原本醒着能获得的知识点值。
代码如下:
#include <iostream>
using namespace std;
const int maxn = 1e5 + 500;
int a[maxn], b[maxn];
int main()
{
int n, k;
cin >> n >> k;
for (int i = 0; i < n; i++)
cin >> a[i];
for (int i = 0; i < n; i++)
cin >> b[i];
int ans = 0, sum = 0, x = 0, y = 0;
for (int i = 0; i < k; i++)
if (b[i] == 0)sum += a[i];
ans = sum; y = k - 1;
for (int i = k; i < n; i++)
{
if (b[i] == 0)sum += a[i];
if (b[i - k] == 0)sum -= a[i - k];
if (sum > ans)
{
ans = sum;
x = i - k;
y = i;
}
}
sum = ans;
for (int i = 0; i < n; i++)
if (b[i] == 1)sum += a[i];
cout << sum << endl;
return 0;
}
C. Chessboard
(水题)
题意:一个被2n*2n的黑白棋盘被分成了4部分,每部分都为n*n(n为奇数),由于某些原因导致棋盘中的格子颜色不对,现在要求你用最少的步数给它上色还原为2n*2n的黑白格棋盘。题目给出一个n,随后给出4个n*n的1,0表(黑白表),用这4个表随机拼凑(位置可以交换,不可旋转)然后改变格子颜色使它还原为2n*2n的黑白棋盘。输出最少染色次数。
解法:求每个n*n的转换为左上角是1和左上角是0的2种情况的分别最少染色次数,再进行随机搭配(2个左上角为1的和2个左上角为0的组合)得到min_ans。
代码如下:
#include <stdio.h>
#include <string>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include<vector>
#include<queue>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn = 1e5 + 500;
int a[10], b[10];
char s[5][105][105];
int main()
{
int n;
while (~scanf("%d", &n))
{
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
for (int i = 0; i < 4; i++)
for (int j = 0; j < n; j++)
scanf("%s", &s[i][j]);
//类型1 左上角为1
for (int i = 0; i < 4; i++)
for (int j = 0; j < n; j++)
for (int k = 0; k < n; k++)
{
if ((j + k) % 2 == 0 && s[i][j][k] == '0')a[i]++;
else if ((j + k) % 2 == 1 && s[i][j][k] == '1')a[i]++;
}
//类型2 左上角为0
for (int i = 0; i < 4; i++)
for (int j = 0; j < n; j++)
for (int k = 0; k < n; k++)
{
if ((j + k) % 2 == 0 && s[i][j][k] == '1')b[i]++;
else if ((j + k) % 2 == 1 && s[i][j][k] == '0')b[i]++;
}
int ans = inf,s1=0;
for (int i = 0; i < 4; i++)
s1 += b[i];
for(int i=0;i<4;i++)
for (int j = i + 1; j < 4; j++)
{
int x = a[i] + a[j] + s1 - b[i] - b[j];
ans = min(ans, x);
}
cout << ans << endl;
}
return 0;
}
D. Pair Of Lines
(计算几何)
题意:给出n个点的坐标(x,y),问你是否能用2条直线过所有点,可以输出YES,反之NO。
解法:对于这种情况,那我们当n<=4是一定成立的,n>4的时候我们可以任意取3个点,先以3点中的2点画一条直线,把该直线不能过的点存入vector中,在对剩下的所有点进行判断,它们是否都在一条直线上,是的话输出YES,不是则取3点中其他2点重复进行上步骤,直到3种情况都没办法实现,那么可以输出NO了。(其实就是一个散点图中,若能用2条直线覆盖所有点,那么容易取三点中的2点必然与其中一条直线重合,复杂问题简单化)
代码如下:
#include <stdio.h>
#include <string>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include<map>
#include<vector>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn = 1e5 + 500;
struct node
{
ll x, y;
}a[maxn];
bool Xmult(node p1, node p2, node p0)
{
return (p1.x - p0.x)*(p2.y - p0.y) - (p2.x - p0.x)*(p1.y - p0.y) == 0 ? true : false;
}
int n;
int vis[maxn];
bool fun()
{
vector<int>q;
int key = 1;
for (int i = 2; i < n; i++)
if (!Xmult(a[0], a[1], a[i]))q.push_back(i);
if (q.size() <= 2)return true;
for (int i = 2; i < q.size(); i++)
if (!Xmult(a[q[0]], a[q[1]], a[q[i]])) {
key = 0; break;
}
if (key)return true;
q.clear(); key = 1;
for (int i = 1; i < n; i++)
if (!Xmult(a[0], a[2], a[i]))q.push_back(i);
if (q.size() <= 2)return true;
for (int i = 2; i < q.size(); i++)
if (!Xmult(a[q[0]], a[q[1]], a[q[i]])) {
key = 0; break;
}
if (key)return true;
q.clear(); key = 1;
for (int i = 0; i < n; i++)
if (!Xmult(a[1], a[2], a[i]))q.push_back(i);
if (q.size() <= 2)return true;
for (int i = 2; i < q.size(); i++)
if (!Xmult(a[q[0]], a[q[1]], a[q[i]])) {
key = 0; break;
}
if (key)return true;
return false;
}
int main()
{
cin >> n;
for (int i = 0; i < n; i++)
scanf("%lld%lld", &a[i].x, &a[i].y);
if (n<=4||fun())
cout << "YES" << endl;
else
cout << "NO" << endl;
return 0;
}
剩下的题留给dalao补充=。=