山东省第一届acm程序设计竞赛题解
缺c 计算几何没看 f一个模拟,不想写,难度不大,J,因为时间挺早的,题目都比较简单,没什么难度,组队出个8题还是轻松的
A:水题
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e3+5; 4 string s[maxn]; 5 6 bool judge(string s1,string s2){ 7 if(s1.length()>s2.length())return 1; 8 int len=s1.length(); 9 for(int i=0;i<len;i++) 10 if(s1[i]!=s2[i]) 11 return true; 12 return false; 13 } 14 15 int main(){ 16 int n; 17 while(cin>>n,n){ 18 bool ok=1; 19 for(int i=0;i<n;i++)cin>>s[i]; 20 21 for(int i=0;i<n;i++) 22 for(int j=i+1;j<n;j++) 23 if(judge(s[i],s[j])&&judge(s[j],s[i])) 24 continue; 25 else { 26 ok=0;break; 27 } 28 29 if(ok)puts("YES"); 30 else puts("NO"); 31 32 } 33 return 0; 34 }
b:输出4联通和8联通的联通快数,水题
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=105; 4 const int dx[]={0,0,1,-1,-1,1,-1,1}; 5 const int dy[]={1,-1,0,0,1,1,-1,-1}; 6 char g[maxn][maxn]; 7 int v[maxn][maxn],n; 8 9 inline bool judge(int x,int y){ 10 if(x<0||x>=n||y<0||y>=n||g[x][y]=='0')return true; 11 return false; 12 } 13 14 void dfs(int x,int y,int t){ 15 if(v[x][y])return ; 16 v[x][y]=1; 17 for(int i=0;i<t;i++){ 18 int nx=x+dx[i]; 19 int ny=y+dy[i]; 20 if(judge(nx,ny))continue; 21 dfs(nx,ny,t); 22 } 23 } 24 25 26 int main(){ 27 int cas=1; 28 while(~scanf("%d",&n),n){ 29 for(int i=0;i<n;i++)scanf("%s",g[i]); 30 memset(v,0,sizeof(v)); 31 32 int res1=0,res2=0; 33 for(int i=0;i<n;i++)for(int j=0;j<n;j++){ 34 if(g[i][j]=='0')continue; 35 if(!v[i][j])res1++; 36 dfs(i,j,4); 37 } 38 memset(v,0,sizeof(v)); 39 for(int i=0;i<n;i++)for(int j=0;j<n;j++){ 40 if(g[i][j]=='0')continue; 41 if(!v[i][j])res2++; 42 dfs(i,j,8); 43 } 44 printf("Case %d: %d %d\n",cas++,res1,res2); 45 puts(""); 46 } 47 return 0; 48 }
d.排下序,水题
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=1e5+5; 5 int d[maxn]; 6 7 int main(){ 8 int n; 9 while(cin>>n,n){ 10 for(int i=0;i<n;i++)cin>>d[i]; 11 sort(d,d+n); 12 ll res=d[n-1]-d[0]; 13 14 for(int i=1;i<n;i++)res+=d[i]-d[i-1]; 15 cout<<res<<endl; 16 } 17 return 0; 18 }
E:n个城市都沦陷了,有两种操作0 x占领x,1 x y,输出x y的最短路
因为每个点只会被占领一次,只要用这个点来更新其他点就好
1 #include<iostream> 2 #include<cmath> 3 #include<string.h> 4 #include<stdio.h> 5 #define INT_MAX 100000 6 using namespace std; 7 int n,m,q; 8 int map[310][310],vis[310]; 9 void floyd(int k){ 10 int i,j; 11 for(i=0;i<n;i++) 12 for(j=0;j<n;j++) 13 { 14 if((map[i][k]!=INT_MAX) && (map[k][j]!=INT_MAX)) 15 if(map[i][j]>map[i][k]+map[k][j]) 16 map[i][j]=map[i][k]+map[k][j]; 17 } 18 } 19 void init() 20 { 21 int i,j; 22 for(i=0;i<310;i++){ 23 for(j=0;j<310;j++) 24 map[i][j]=INT_MAX; 25 map[i][i]=0; 26 } 27 } 28 int main() 29 { 30 int i,j,k,l,x,y,z,d,c=0; 31 while(cin>>n>>m>>q&&(n||m||q)) 32 { 33 init(); 34 memset(vis,0,sizeof(vis)); 35 for(int i=0;i<m;i++){ 36 cin>>x>>y>>z; 37 if(map[x][y]>z) 38 map[x][y]=z; 39 } 40 printf("Case %d:\n",++c); 41 for(j=0;j<q;j++){ 42 cin>>d; 43 if(!d){ 44 cin>>x; 45 if(!vis[x]){ 46 vis[x]=1; 47 floyd(x); 48 } 49 else printf("City %d is already recaptured.\n",x); 50 } 51 else{ 52 cin>>x>>y; 53 if(!vis[x]||!vis[y]) 54 printf("City %d or %d is not available.\n",x,y); 55 else if(map[x][y]==INT_MAX) 56 cout<<"No such path."<<endl; 57 else cout<<map[x][y]<<endl; 58 } 59 } 60 cout<<endl; 61 } 62 return 0; 63 }
F:模拟题,题意难读,不过好写,110行就差不多能写完
G:n个数,从中取四个数,每个数可以重复取,输出小于等于M的最大值
先把两个数和的存下来,排个序,然后双指针就Ok
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=1e3+5; 5 int d[maxn],c[maxn*maxn]; 6 int n,m; 7 8 int main(){ 9 int cas=1; 10 while(cin>>n>>m,n){ 11 for(int i=0;i<n;i++)cin>>d[i]; 12 int cnt=0; 13 for(int i=0;i<n;i++)for(int j=0;j<n;j++) 14 c[cnt++]=d[i]+d[j]; 15 16 sort(c,c+cnt); 17 18 int l=0,r=cnt-1; 19 ll res=0; 20 while(c[r]>m)r--; 21 22 while(l<=r){ 23 if((ll)c[l]+c[r]>m)r--; 24 else { 25 res=max(res,(ll)c[l]+c[r]); 26 l++; 27 } 28 if(res==m)break; 29 } 30 printf("Case %d: %lld\n\n",cas++,res); 31 } 32 return 0; 33 }
H:输出在(x,y)右边以及下面的第一个点,具体要求看题目
n只有300,直接爆
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1005; 4 int x[maxn],y[maxn],z[maxn]; 5 6 int main(){ 7 int n,cas=1; 8 while(cin>>n,n){ 9 for(int i=0;i<n;i++)cin>>x[i]>>y[i],z[i]; 10 11 int nx,ny; 12 printf("Case %d:\n",cas++); 13 for(int i=0;i<n;i++){ 14 nx=ny=-1; 15 for(int j=0;j<n;j++) 16 if(x[j]>x[i]&&y[j]>y[i]){ 17 if(nx==-1)nx=x[j],ny=y[j]; 18 else if(x[j]<nx)nx=x[j],ny=y[j]; 19 else if(x[j]==nx&&y[j]<ny)ny=y[j]; 20 } 21 printf("%d %d\n",nx,ny); 22 } 23 puts(""); 24 } 25 return 0; 26 }
I:上一题的加强版,可以加入一个点,删除一个点,然后查询一个点的右下方点,要求和上面一样
分析:讲道理写了个AVL插入两个元素应该没问题,迷之超时,set套pair,找到第然后二分找一下点,然后符合要求的肯定在后面,找到第一个点就好了
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 set< pair<int,int> >st; 5 set< pair<int,int> >::iterator it; 6 7 int main(){ 8 int n;pair<int,int>p; 9 int ca=1; 10 while (~scanf("%d",&n)&&n){ 11 st.clear(); 12 printf("Case %d:\n",ca++); 13 for (int i=0;i<n;i++){ 14 char op[8]; 15 scanf("%s%d%d",op,&p.first,&p.second); 16 if (op[0]=='a') st.insert(p); 17 else if ((op[0]=='r')) st.erase(p); 18 else{ 19 it=st.upper_bound(p); 20 for(;it!=st.end();it++) 21 if(it->first>p.first&&it->second>p.second) 22 break; 23 if (it==st.end()) puts("-1"); 24 else printf("%d %d\n",it->first,it->second); 25 } 26 } 27 puts(""); 28 } 29 }
J:题目太长,没看