网址链接:Toyota Programming Contest 2024#8(AtCoder Beginner Contest 365) - AtCoder
A题:
题目很简单就是判断是否是闰年,然后根据是否是闰年来给出所给年份的天数,如果是润年那么是366天,如果不是闰年那么就是365天
代码实现:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
if(n%400==0 || (n%4==0 && n%100!=0)) cout<<"366"<<endl;
else cout<<"365"<<endl;
return 0;
}
B题:
输出第二大的值的下标,使用结构体,进行排序后输出第二大的下标即可
代码实现:
#include<bits/stdc++.h>
using namespace std;
const int N=105;
struct node
{
int val;
int index;
}a[N];
bool cmp(node x, node y)
{
return x.val>y.val;
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i].val;
a[i].index=i;
}
sort(a+1,a+1+n,cmp);
cout<<a[2].index<<endl;
return 0;
}
C题:
C - Transportation Expenses (atcoder.jp)
问题陈述
有 N 人参加一项活动, i /人的交通费用是 Ai 日元。
活动组织者高桥(Takahashi)决定设定交通补贴的最高限额为 x 。 i 人的补贴为 min(x,Ai)日元。这里, x 必须是一个非负整数。
高桥的预算为 M 日元,他希望所有 N 人的交通补贴总额最多为 M 日元,那么补贴限额 x 的最大可能值是多少?
如果补贴限额可以无限大,请报告。
Constraints
- 1≤N≤2×105
- 1≤M≤2×10^14
- 1≤Ai≤109
- All input values are integers.
思路:
x的取值范围是从0到1 1e9 , 如果x 大于1e9 的话,所有的min(A[i],x) 都是A[i] ,因为题干中A[i] 的取值范围小于等于 1e9 , 这道题我们使用二分答案,l =0; r= 1e9 , 然后看看mid 满不满足条件, 如果满足条件的话,我们就让l= mid .如果不满足条件的话, 我们就缩小范围,r=mid-1 。
为什么呢,如果说mid 已经满足条件了,那么我们就需要看看比mid大的数中有没有可以满足条件的,因为题干要就使补贴限额x 的最大尽可能的大,如果mid不满足条件,我们就让r= mid-1;
代码实现:
#include<bits/stdc++.h>
using namespace std;
const int N=200010;
int n;
long long M;
int A[N];
bool check(int x)
{
long long sum=0;
for(int i=1;i<=n;i++)
{
sum+=min(A[i],x);
if(sum>M) return false;
}
return true;
}
int main()
{
cin>>n>>M;
for(int i=1;i<=n;i++) cin>>A[i];
int l=0; int r=1e9;
while(l<r)
{
int mid=l+(r-l+1)/2;
if(check(mid)) l=mid;
else r=mid-1;
}
if(l==1e9) cout<<"infinite"<<endl;
else cout<<l<<endl;
return 0;
}
D题:
问题陈述
高桥和青木玩了 N 次石头剪刀布。[注:在这个游戏中,石头赢剪刀,剪刀赢纸,纸赢石头。
青木的动作由长度为 N 的字符串 S 表示,字符串由 "R"、"P "和 "S "组成。 i /th字符 S 表示青木在 i /th对局中的棋步:R "表示 "石头","P "表示 "纸","S "表示 "剪刀"。
高桥的棋步满足以下条件:
- 高桥从未输给过青木。
- 对于 i=1,2,…,N−1 ,高桥在 i /th对局中的棋步与他在 (i+1) /th对局中的棋步不同。
请确定高桥的最大胜局数。
可以保证存在一个满足这些条件的高桥下棋顺序。
Constraints
- 1≤N≤2×105
- S is a string of length N consisting of
R
,P
, andS
. - N is an integer.
思路讲解:
D题的话,在比赛当中我没有做出来,我是用贪心做的,就是再如果有可能赢的情况下就让他赢,因为题干已经说了,他不可能输,因此,他每局只有赢或者是平两种情况,我就让他如果这句可以赢的那种抉择如果上一局没有使用的话,就让其在这一局中使用,让他赢,否则就平,这种策略的话,只考虑了眼前的一步,因为你的决策可能会对后续的出法产生影响,因此要使用动态规划,来求取最优解。
dp[i][j] 表示 经历 i 次 出手, 第 i 次 我出 j 所能赢得的最大胜利场数可以让 0 代表 S, 1 代表 R, 2 代表 P 具体看代码吧
代码实现:
#include<bits/stdc++.h>
using namespace std;
const int N=200010;
int dp[N][3];
int main()
{
int n;
cin>>n;
string S;
cin>>S;
S=' '+S;
/// 0->S
/// 1->R
/// 2->P
for(int i=1;i<=n;i++)
{
if(S[i]=='S')
{
dp[i][1]=max(dp[i-1][0],dp[i-1][2])+1; // 因为对手出的是剪刀,我们不能输,只能出石头1 赢
dp[i][0]=max(dp[i-1][1],dp[i-1][2]);//或者剪刀0 平 又要和上局不一样 这一局是1, 则上一局只能是0 或者是 2
}
else if(S[i]=='R')
{
dp[i][2]=max(dp[i-1][0],dp[i-1][1])+1;
dp[i][1]=max(dp[i-1][0],dp[i-1][2]);
}
else
{
dp[i][0]=max(dp[i-1][1],dp[i-1][2])+1;
dp[i][2]=max(dp[i-1][0],dp[i-1][1]);
}
}
cout<<max({dp[n][0],dp[n][1],dp[n][2]})<<endl;
return 0;
}