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;
}
posted @ 2023-01-11 12:26  Forever1507  阅读(43)  评论(0编辑  收藏  举报