2020 ICPC Shanghai Site记录
B
模拟了一个扫雷游戏!
我需要把两个图的示数和变成相等的!
我发现一个图里,雷变空格空格变雷之后示数不变!
我发现操作数只要不超过 \(\frac{n\times m}{2}\) 就可以了!
那么根据抽屉原理,我只要把B改成A或者A的反图即可!
查看代码
#include<bits/stdc++.h>
using namespace std;
int n,m,sum1,sum2;
char a[1005][1005],b[1005][1005];
int main(){
ios::sync_with_stdio(0);
cin>>n>>m;
for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)cin>>a[i][j];
for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)cin>>b[i][j];
for(int i=1;i<=n;++i)for(int j=1;j<=m;++j){
if(a[i][j]!=b[i][j])sum1++;
}
if(sum1<=n*m/2){
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j)cout<<a[i][j];
cout<<'\n';
}
}
else for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j)if(a[i][j]=='X')cout<<'.';else cout<<'X';
cout<<'\n';
}
}
D
看了这个题 \(1\min\) 后:这不是一个申必分讨?
\(\text{Wrong answer on test 2}\)
哦!我少考虑了情况!
我还可以对着走!
\(\text{Wrong answer on test 2}\)
我还少讨论了情况!
\(\text{Wrong answer on test 8}\)
放弃分讨。
我发现,除了一个人走完,或者对着走,一定是中间一个点让两人到达的时间相等!
于是我写了个二分。
过了!
查看代码
#include<bits/stdc++.h>
using namespace std;
int t;
double eps=1e-7;
//p1+(p2-p1)/(v1+v2)*v1
double n,p1,v1,p2,v2;
double work(){
double ans1=max(p2/v2,(n-p1)/v1),ans2=(p1+n+n-p2)/(v1+v2);
double ans3=min(n+p1,n+n-p1)/v1,ans4=min(n+p2,n+n-p2)/v2;
double t=(p2-p1)/(v1+v2);
double ans5=t+max((p1+t*v1)/v1,(n-(p1+t*v1))/v2);
double ans6=max(p1/v1,min((p2-p1+n-p1)/v2,(n-p2+n-p1)/v2));
double ans7=max((n-p2)/v2,min((p1+p2)/v1,(p2-p1+p2)/v1));
double x=(p1+p2)/(v1+v2);
double ans8=x+(n-p2+v2*x)/max(v1,v2);
double p=(n+n-p1-p2)/(v1+v2);
double ans9=p+(p1+v1*p)/max(v1,v2);
// printf("%.8lf %.8lf %.8lf %.8lf\n",ans1,ans2,min(ans3,ans4),ans5);
return min(ans1,min(ans2,min(ans3,min(ans4,min(ans5,min(ans6,min(ans7,min(ans8,ans9))))))));
}//这一坨是分类讨论时期的残留,反正不会挂就加上吧(
double work2(){
double lt=p1-eps,rt=p2+eps,ans=1e9;
while(lt+eps<rt){
double mid=(lt+rt)/2;
double ans1=min((p1+mid),mid+mid-p1)/v1;
double ans2=min((n-mid+n-p2),p2-mid+n-mid)/v2;
ans=min(ans,max(ans1,ans2));
if(ans1+eps<ans2)lt=mid;
else if(ans2+eps<ans1)rt=mid;
else return ans1;
}
return ans;
}
int main(){
cin>>t;
while(t--){
cin>>n>>p1>>v1>>p2>>v2;
if(p1>p2)swap(p1,p2),swap(v1,v2);
printf("%.8lf\n",min(work(),work2()));
}
}
M
我发现我可以建成一棵树!
然后只要从根节点向下贪心,没有要保留的就直接删!
记得特判不能删根目录!
做完了!
查看代码
#include<bits/stdc++.h>
using namespace std;
int t,n,m;
map<string,int>mpp;
vector<int>nbr[1005];
bool vis[1005];
bool viss[1005];
int ans;
void dfs(int cur){
for(auto to:nbr[cur]){
dfs(to);
vis[cur]|=vis[to];
}
}
void dfss(int cur){
if(!vis[cur]&&cur!=0||nbr[cur].size()==0&&!vis[cur]){
ans++;
return;
}
for(auto to:nbr[cur]){
dfss(to);
}
}
int main(){
ios::sync_with_stdio(0);
cin>>t;
while(t--){
memset(vis,0,sizeof(vis));
memset(viss,0,sizeof(viss));
ans=0;
cin>>n>>m;
mpp.clear();
for(int i=0;i<=1000;++i)nbr[i].clear();
int maxn=0,tot=0;
for(int i=1;i<=n+m;++i){
string ss;
cin>>ss;
ss+="/";
// cout<<"Test: "<<ss<<'\n';
int cnt=0,lst=0;
for(int j=0;j<ss.size();++j){
if(ss[j]=='/'){
string str=ss.substr(0,j+1);
// cout<<str<<'\n';
int x=mpp[str];
bool flg=0;
if(x==0)mpp[str]=x=++tot,flg=1;
if(i>n)vis[x]=1;
if(flg)nbr[lst].push_back(x)/*,cout<<"Edge: "<<lst<<' '<<x<<'\n'*/;
lst=x;
}
}
}
dfs(0);
dfss(0);
cout<<ans<<'\n';
}
}
H
我可以枚举第一个人吃哪碗饭,假设枚举到 \(i\)。
然后不难发现第 \(j\) 个人吃 \(i+j-1\) 碗最优(对 \(k\) 取模)。
然后弄出顺时针距离和逆时针距离。
然后就是分成两组,一组逆时针,一组顺时针,要求这两组的最大值的和的最小值!
钦定一个类型从大到小排序,预处理最大值即可!
这样就做完了!
查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int t,n,k,a[1005],b[1005];
struct node{
int x,y;
}p[1005];
bool cmp(node a,node b){
return a.x>b.x;
}
int maxn[1005];
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--){
cin>>n>>k;
for(int i=1;i<=k;++i)cin>>a[i];
for(int i=1;i<=k;++i)cin>>b[i];
sort(a+1,a+k+1);
sort(b+1,b+k+1);
int ans=1e18;
for(int i=1;i<=k;++i){
//第1个人选择第 i 碗
int now=i;
for(int j=1;j<=k;++j){
// cout<<"now = "<<now<<endl;
p[j].x=(a[j]-b[now]+n)%n;
p[j].y=(b[now]-a[j]+n)%n;
now++;if(now>k)now-=k;
}
sort(p+1,p+k+1,cmp);
// for(int j=1;j<=k;++j)cout<<p[j].x<<' '<<p[j].y<<'\n';
memset(maxn,0,sizeof(maxn));
for(int j=1;j<=k;++j)maxn[j]=max(maxn[j-1],p[j].y);
int mini=1e18;
p[k+1].x=0;
for(int j=1;j<=k+1;++j)mini=min(mini,min(2*p[j].x+maxn[j-1],p[j].x+2*maxn[j-1]));
ans=min(ans,mini);
}
cout<<ans<<'\n';
}
return 0;
}