A - Seats
思路:从前往后扫,判断有多少个'.'的左右各有一个'#'
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
string s;
signed main()
{
cin>>n;
cin>>s;
int cnt=0;
if(s.size()<3)
{
cout<<0<<"\n";
return 0;
}
if(s.size()>=3)
for(int i=1;i<=s.size()-2;i++)
{
if(s[i]=='.'&&s[i-1]=='#'&&s[i+1]=='#')
{
cnt++;
}
}
cout<<cnt<<"\n";
return 0;
}
B - Traveling Takahashi Problem
思路:正常用double模拟一下
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
double x,y;
signed main()
{
double flagx=0,flagy=0;
double sum;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x>>y;
sum+=sqrt((x-flagx)*(x-flagx)+(y-flagy)*(y-flagy));
flagx=x,flagy=y;
}
sum+=sqrt(flagx*flagx+flagy*flagy);
printf("%.7lf",sum);
return 0;
}
C - Spiral Rotation
题意:就是说,最外层操作一次,然后往里一层就多操作一次,这个操作就是说将整个图顺指针旋转90度,我们可以记录每个点操作多少次,然后直接输出即可
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
char s[3005][3005];
char c[3005][3005];
signed main()
{
cin >> n;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
cin >> s[i][j];
}
}
for(int x = 1; x <= n; x++)
{
for(int y = 1; y <= n; y++)
{
int num = min(min(x, n - x + 1), min(y, n - y + 1)) % 4;
if(num == 0) {
c[x][y] = s[x][y];
}
else if(num == 1) {
c[x][y] = s[n - y + 1][x];
}
else if(num == 2) {
c[x][y] = s[n - x + 1][n - y + 1];
}
else if(num == 3) {
c[x][y] = s[y][n - x + 1];
}
}
}
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
cout << c[i][j];
}
cout << "\n";
}
return 0;
}
D - ABA
思路:一开始我想的使用map<char,vector<int>> 去统计每个字符之前出现的位置,然后都用当前位置进行操作,然后判断有哪些是符合的,然后发现时间复杂度是O(n^2)肯定会超时,后面就想到了优化后的思路
我们可以用一个map<char,int>cnt去统计当前所有字符之前所出现的次数,然后用map<char,int>sum去统计之前出现的字符串的位置和
然后我们每次的贡献就是(i-1)*cnt[s[i]]-sum[s[i]]
输出即可
#include<bits/stdc++.h>
using namespace std;
#define int long long
string s;
map<char,int> mpsum;//统计之前出现的位数总和
map<char,int> mpcnt;//统计上之前出现的次数
signed main()
{
cin>>s;
int sum=0;
for(int i=0;i<s.size();i++)
{
sum+=(i-1)*mpcnt[s[i]]-mpsum[s[i]];
mpsum[s[i]]+=i;
mpcnt[s[i]]++;
}
cout<<sum;
return 0;
}
E - 3 Team Division
思路:就是看将整个分成三等份最小的操作次数,我们可以用dp去存储将其分成三等份所需的最小步数,dp[j][k]表示前i个分成j和k的容量的最小操作次数
#include<bits/stdc++.h>
using namespace std;
#define int long long
struct node
{
int x;//表示组数
int y;//表示强度
}a[105];
int n;
void solve()
{
cin>>n;
vector<int> pre(n+1,0);
for(int i=1;i<=n;i++)
{
cin>>a[i].x>>a[i].y;
pre[i]=pre[i-1]+a[i].y;
}
if(pre[n]%3!=0)
{
cout<<"-1\n";
return ;
}
int s=pre[n]/3;
int f[s+1][s+1];
int g[s+1][s+1];
memset(f,0x3f3f3f3f,sizeof(f));
memset(g,0x3f3f3f3f,sizeof(g));
f[0][0]=0;
for(int i=1;i<=n;i++)
{
int pos=a[i].x;
int val=a[i].y;
for(int j=0;j<=s;j++)
{
for(int k=0;k<=s;k++)
{
g[j][k]=0x3f3f3f3f;
if(val<=j)
{
g[j][k]=min(g[j][k],f[j-val][k]+(pos!=1));
}
if(val<=k)
{
g[j][k]=min(g[j][k],f[j][k-val]+(pos!=2));
}
if(val<=pre[i]-j-k)
{
g[j][k]=min(g[j][k],f[j][k]+(pos!=3));
}
}
}
for(int j=0;j<=s;j++)
{
for(int k=0;k<=s;k++)
{
swap(f[j][k],g[j][k]);
}
}
}
cout<<(f[s][s]==0x3f3f3f3f?-1:f[s][s])<<"\n";
}
signed main()
{
int t=1;
while(t--)
solve();
return 0;
}