这场4题铜,5~6题银
M Gitignore
去年比赛的时候还没用过git,被题意整懵了硬是看了巨久。然后场上的思路是模拟,结果码力太差没写出来,tcl。
题意:gitignore,上传文件,n个路径是要删的,m个路径是不能删的,问最小删几个文件。
思路:
对于m个不能删的,把他所有的父目录都标注为1保护起来。
然后再去遍历n个要删的,令ans=n,如果目录vis为0,说明没有被保护,并第一次出现,标注为2,碰到标注为2的,说明没被保护,且前面出现过,就可以合并,那么ans-1
代码:
#include<bits/stdc++.h>
#include<iostream>
#include <stdio.h>
using namespace std;
const int maxn=2005;
const int base=131;
typedef long long ll;
#define pi acos(-1)
#define INF 0x3f3f3f3f
#define mod 998244353
const int inf=1<<30;
vector<int> g[maxn];
vector<string> str1,str2;
map<string,int> vis;
int main()
{
//freopen("data.in","r",stdin);
//freopen("1.out","w",stdout);
ios::sync_with_stdio(false); cin.tie(0);
int t,n,m;
cin>>t;
while(t--){
cin>>n>>m;
string s;
vis.clear();
str1.clear();
str2.clear();
for(int i = 0; i< n;i++){
cin>>s;
str1.push_back(s);
}
for(int i = 0; i< m;i++){
cin>>s;
str2.push_back(s);
string ss="";
for(int j = 0; j < s.size(); j++){
ss += s[j];
if(s[j] == '/'||j == s.size() - 1){
vis[ss] = 1;
// cout<<ss<<endl;
}
}
}
int ans = n;
for(int i = 0;i < n; i++){
string ss = "";
for(int j = 0;j < str1[i].size(); j++){
ss += str1[i][j];
if(str1[i][j] == '/'||j == str1[i].size() - 1){
//cout<<ss<<endl;
if(vis[ss] == 2){
ans--;
break;
}
if(vis[ss] == 0)
vis[ss] = 2;
}
}
}
cout<<ans<<endl;
}
return 0;
}
B Mine Sweeper II
思路:
思维题,看B能否在 [ n m 2 ] [\frac{nm}{2}] [2nm]步内变为A或A的相反矩阵(也就是X变成 . . ., . . .变成X)
代码:
#include<bits/stdc++.h>
using namespace std;
int n,m;
string s1[1005],s2[1005];
int main()
{
std::ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=0;i<n;i++)
cin>>s1[i];
for(int i=0;i<n;i++)
cin>>s2[i];
int cnt1,cnt2;
cnt1 =cnt2=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(s2[i][j]!=s1[i][j]) cnt1++;
if(s2[i][j]==s1[i][j])
cnt2++;
}
}
if(cnt1<=(m*n)/2) {
for(int i = 0;i<n;i++)
cout<<s1[i]<<endl;
}
else if(cnt2<=(m*n)/2){
for(int i = 0;i<n;i++){
for(int j = 0 ;j < m;j++){
if(s1[i][j] == 'X')
cout<<".";
else
cout<<"X";
}
cout<<endl;
}
}
else
{
cout<<-1<<endl;
}
system("pause");
return 0;
}
D Walker
题意:
给定一段路的距离,两个人的初始位置,速度,问最小需要多少时间走完全部路程。
思路:
分三种情况讨论,第一种一个人跑完全部,取两个人都跑完的较小情况。
第二种两个人对着走,也就是第一个人走p1到n,第二个人走0到p2。
第三种两个人都到中间任意一点,再反转回各自的方向,取两个人走完的最大值。对于这个点的具体位置可以二分求解。
代码:
#include<bits/stdc++.h>
using namespace std;
double n,p1,v1,p2,v2,p3;
double ans;
double cal(double x,double p,double v){
return min(x + p,x + x - p) / v;
}
double slove(double l,double r)
{
for(int i = 0; i < 100 ; i++){
double m = (l + r) / 2.0;
double ll = cal(m,p1,v1);
double rr = cal(n - m,p2 - m,v2);
ans = min(ans,max(ll,rr));
if(ll < rr)
l = m;
else
r = m;
}
return ans;
}
int main()
{
std::ios::sync_with_stdio(false);
int t;
cin>>t;
while(t--){
cin>>n>>p1>>v1>>p2>>v2;
if(p1 > p2){
swap(p1,p2);
swap(v1,v2);
}
double t1 = min(cal(n,p1,v1),cal(n,p2,v2));
double t2 = max((n - p1) / v1,p2 / v2);
ans = min(t1,t2);
double t3 = slove(p1,p2);
printf("%.10lf\n",ans);
}
return 0;
}
I Sky Garden
代码:
#include<bits/stdc++.h>
#include<iostream>
#include <stdio.h>
using namespace std;
const int maxn=2005;
const int base=131;
typedef long long ll;
#define pi acos(-1)
#define INF 0x3f3f3f3f
#define mod 998244353
const double PI = acos(-1);
const int inf = 1<<30;
double a[maxn],b[maxn];
int main()
{
//freopen("data.in","r",stdin);
//freopen("1.out","w",stdout);
ios::sync_with_stdio(false); cin.tie(0);
int n,m;
cin>>n>>m;
double cnt = 0.0;
for(int i = 1; i < 2 * m;i++){
cnt += min(2.0, PI * min(i*1.0,2.0 * m - i) / m);
}
a[1] = b[1] = cnt;
for(int i = 2;i <= n;i++){
b[i] = i * 1.0 * b[1];
a[i] = a[i - 1] + b[i] + 2.0 * m * (i - 1);
}
double ans = 0.0;
for(int i =1 ;i <= n;i++){
ans += (a[i] - b[i]) * 2.0 * m + b[i] * 2.0 * m / 2.0;
if(m > 1)
ans += 2.0 * m * i;
}
printf("%.10lf\n",ans);
return 0;
}