A题:
已知需要a分钟睡觉,那么分三种情况:
1.a<=b,那么睡够a分钟,闹钟还是没响.
2.d>=c,那么他还没睡觉就被吵醒了.
3.先计算睡觉要多少个周期,即a-b为被b这个闹钟吵醒后还需要睡的分钟数,c-d就是它被每个c闹钟吵醒前能睡的分钟数,那么(a-b)/(c-d)就是需要睡觉的周期(注意:可能(a-b)/(c-d)不能整除,相当于你睡觉需要8分钟(a-b),你每次小盹5分钟(c-d),那么(a-b)/(c-d)=1但是其实你需要睡两次,即答案是2才对,所以这里需要特判一下).
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#define ll long long
using namespace std;
int main()
{
int T;
cin >> T;
for (int i = 0; i < T; i++)
{
ll a, b, c, d;
cin >> a >> b >> c >> d;
ll ans = b;
if (a <= b)
{
cout << ans << endl;
continue;
}
if (d >= c) ans = -1;
else
{
ll t = (a - b) / (c - d);
//(a-b)%(c-d)为特判
ans += (t+ bool((a - b) % (c - d))) * c;
}
cout << ans << endl;
}
return 0;
}
B题:
水题就不多说了
#include<iostream>
#include<string>
#define ll long long
using namespace std;
int main()
{
int T;
cin >> T;
while (T--)
{
string a;
ll pos1 = 0, pos2 = 0, pos3 = 0, ans = 1e10, minnum = 1e10;
cin >> a;
a = '0' + a;
for (int i = 1; i < a.length(); i++) {
if (a[i] == '1')pos1 = i;
else if (a[i] == '2')pos2 = i;
else if (a[i] == '3')pos3 = i;
if (pos1 && pos2 && pos3) {
ll temp = min(pos1, min(pos2, pos3));
ans = min(ans, i - temp + 1);
}
}
if (ans != 1e10)
cout << ans << endl;
else
cout << '0' << endl;
}
}
C题:
输入n,创造一个2n边型,问包裹住这个2n边型的最小正方形的边长是多少:
#include<iostream>
using namespace std;
#include<cmath>
#include<iomanip>
int main()
{
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
n *= 2;
double ans = 1.0 / tan(3.1415926535 / n);
cout << setprecision(10) << ans << endl;
}
}
D题:
和上一题一样,只不过这里的n是奇数:
推到过程如下:
#include<iostream>
using namespace std;
#include<cmath>
#include<iomanip>
int main()
{
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
n *= 2;
double ac = 1.0 / sin(3.1415926535 / n);
double ab = cos(3.1415926535 / (2 * n)) * ac;
printf("%.9lf\n", ab);
}
}
E题:
说白了就是判断人在人行道时不能有车能撞到他.
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#define ll long long
int person[5];
int car[5][5];
using namespace std;
int main()
{
int ans = 0;
for (int i = 0; i < 4; i++) {
cin >> car[i][0] >> car[i][1] >> car[i][2] >> person[i];
}
for (int i = 0; i < 4; i++) {
if(person[i]){
for (int j = 0; j < 4; j++) {
if (car[i][j]) { ans = 1; break; }
}
for (int j = 1; j <= 3; j++) {
if(car[(i+j)%4][(j-1)%3]) { ans = 1; break; }
}
}
}
if (ans)cout << "YES" << endl;
else cout << "NO" << endl;
return 0;
}
F题:DFS或者DP(都写不出来了)
DP链接:
https :blog.csdn.net/a664607530/article/details/72842135
解题思路:DP,每一层的左楼梯和右楼梯都有两个选择策略,左楼梯可以是下面层的右楼梯走过来的,也可以是下面层的左楼梯先去关灯在走回来的,右楼梯一样。在特殊考虑一下相当只有一层的。
注解和代码如下:
#pragma warning(disable:4996)
#include<iostream>
using namespace std;
#include<cmath>
#include<iomanip>
#include<string>
#include<cstring>
const int INF = 0x3f3f3f3f;
int n, m;
char ch[20][120];
int l[20], r[20], visit[20], dp[20][2];
int main()
{
while (cin>>n>>m)
{
memset(visit, 0, sizeof visit);
memset(r, 0, sizeof r);
memset(l, 0, sizeof l);
for (int i = n; i >= 1; i--)
{
cin >> ch[i] + 1;
for (int j = 2; j <= m + 1; j++)
if (ch[i][j] == '1') { l[i] = j;visit[i] = 1; break; }
for (int j = m + 1; j >= 2; j--)
if (ch[i][j] == '1') {r[i] = j;break; }
}
//特判只有一层的情况
int x = n;
while (!visit[x--] && x >= 1) n--;
if (n == 1) { printf("%d\n", r[1] ? r[1] - 1 : 0); continue; }
//普遍情况
memset(dp, INF, sizeof dp);
dp[1][0] = r[1] ? (r[1] - 1) * 2 : 0, dp[1][1] = m + 1;
for (int i = 2; i < n; i++)
{
//如果这一层都没有灯是开的话
if (!visit[i])
{
dp[i][0] = dp[i - 1][0] + 1;
dp[i][1] = dp[i - 1][1] + 1;
continue;
}
//左楼梯下面的左楼梯先去关灯在走回来的
dp[i][0] = min(dp[i - 1][0] + 2 * (r[i] - 1) + 1, dp[i][0]);
//左楼梯下面层的右楼梯走过来的
dp[i][0] = min(dp[i - 1][1] + m + 1 + 1, dp[i][0]);
//右楼梯下面层的右楼梯关灯走过来的
dp[i][1] = min(dp[i - 1][1] + 2 * (m + 2 - l[i]) + 1, dp[i][1]);
//右楼梯下面的左楼梯走过来的
dp[i][1] = min(dp[i - 1][0] + m + 2, dp[i][1]);
}
int ans = min(dp[n - 1][0] + r[n], dp[n - 1][1] + 1 + m + 2 - l[n]);
printf("%d\n", ans);
}
return 0;
}
这次的题非常的NICE