2015 SWJTU 校集训队选拔赛 Ⅱ参考题解
来源:互联网 发布:淘宝店铺页面背景图 编辑:程序博客网 时间:2024/05/20 20:42
A、排序
其实这题的话不能乱YY,仔细看下提供的sort代码可以发现其实就是对奇数位的数以及偶数位的数字分别进行排序,那我们只要输入的同时按奇偶位存下数字然后排序与原数组排序的对比就可以了。
代码:
#include <iostream>#include <cmath>#include <string>#include <vector>#include <algorithm>#include <set>#include <map>#include <cstdio>#include <cctype>#include <numeric>#include <cstring>#include <climits>#include <utility>#include <stack>using namespace std;int a[100005];vector <int> v,w;bool f;void init(){ f=true; v.clear(); w.clear();}int main(){ //freopen("data.in","r",stdin); //freopen("data.out","w",stdout); int n; while(scanf("%d",&n)==1) { init(); for(int i=0; i<n; ++i) { scanf("%d",a+i); if(f) { v.push_back(a[i]); f=!f; } else { w.push_back(a[i]); f=!f; } } sort(v.begin(),v.end()); sort(w.begin(),w.end()); sort(a,a+n); bool fs=false; int cnt,cntt; cnt=cntt=0; f=true; for(int i=0; i<n; ++i) { if(f) { fs=(v[cnt++]==a[i])?false:true; f=!f; } else { fs=(w[cntt++]==a[i])?false:true; f=!f; } if(fs)break; } if(fs)puts("NO"); else puts("YES"); } return 0;}
B、Search For The Golden
这是一题搜索题BFS、DFS应该都能过(因为数据量不大~) ,思路大概就是先从起点去拿钥匙 不开门 其实如果直接判能不能开门也是可以的 我就懒得改了-- 然后再去搜整张图 要注意拿到钥匙后就拿到了 has++递归回来之后 不要再减回去 因为你已经能拿到了这把钥匙为什么还要放下来退回去??其他就没什么坑了~
代码:
#include <cstring>#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <vector>#include <map>#include <set>#include <queue>#include <climits>#include <utility>using namespace std;int n,m,ex,ey,sx,sy;char mp[25][25];int dirx[]= {0,0,1,-1};int diry[]= {1,-1,0,0}; //right left up downbool vis[25][25];bool was[25][25];struct point{ int has; int total;} p[15];bool dfs(int x,int y){ if(x==ex&&y==ey)return true; for(int i=0; i<4; ++i) { int nx=x+dirx[i]; int ny=y+diry[i]; if(nx<0||nx>=n||ny<0||ny>=m)continue; if(mp[nx][ny]>='A'&&mp[nx][ny]<='E')continue; if(mp[nx][ny]!='X'&&!vis[nx][ny]) { vis[nx][ny]=true; if(dfs(nx,ny))return true; vis[nx][ny]=false; } } return false;}bool dfsall(int x,int y){ if(mp[x][y]=='G')return true; for(int i=0; i<4; ++i) { int nx=x+dirx[i]; int ny=y+diry[i]; if(nx>=0&&nx<n&&ny>=0&&ny<m&&!vis[nx][ny]&&mp[nx][ny]!='X') { if(mp[nx][ny]=='.') { vis[nx][ny]=true; if(dfsall(nx,ny))return true; vis[nx][ny]=false; } else if(mp[nx][ny]=='G') { if(dfsall(nx,ny))return true; } else if(mp[nx][ny]>='a'&&mp[nx][ny]<='e') { if(!was[nx][ny]) { was[nx][ny]=true; p[mp[nx][ny]-'a'].has++; vis[nx][ny]=true; if(dfsall(nx,ny))return true; vis[nx][ny]=false; } else { vis[nx][ny]=true; if(dfsall(nx,ny))return true; vis[nx][ny]=false; } } else if(mp[nx][ny]>='A'&&mp[nx][ny]<='E') { if(p[mp[nx][ny]-'A'].has==p[mp[nx][ny]-'A'].total&&p[mp[nx][ny]-'A'].total) { vis[nx][ny]=true; if(dfsall(nx,ny))return true; vis[nx][ny]=false; } else continue; } } } return false;}void init(){ memset(was,false,sizeof(was)); memset(p,0,sizeof(p));}int main(){ //freopen("data.in","r",stdin); //freopen("data.out","w",stdout); while(scanf("%d%d",&n,&m)==2) { if(n==0&&m==0)break; init(); for(int i=0; i<n; ++i) { scanf("%s",&mp[i]); for(int j=0; j<m; ++j) { if(mp[i][j]>='a'&&mp[i][j]<='e')p[mp[i][j]-'a'].total++; if(mp[i][j]=='S') { sx=i; sy=j; } } } for(int i=0; i<n; ++i) { for(int j=0; j<m; ++j) { if(mp[i][j]>='a'&&mp[i][j]<='e') { memset(vis,false,sizeof(vis)); vis[sx][sy]=true; ex=i; ey=j; if(dfs(sx,sy)) { p[mp[i][j]-'a'].has++; was[i][j]=true; } } } } memset(vis,false,sizeof(vis)); vis[sx][sy]=true; if(dfsall(sx,sy))puts("YES"); else puts("NO"); } return 0;}
C、最大覆盖
其实这一题不算是一个计算几何的问题,主要是一个想法题,可以采用类似扫描线的方式。令一条线段头为true尾部则为false,所以我们可以结构体对其排序(具体见代码),然后来一个点true则+1,否则-1,过程更新ans,取最大值。
代码:
#include <cstring>#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <vector>#include <map>#include <set>#include <queue>#include <climits>using namespace std;struct point {int num;bool f;}p[100005*2];bool cmp(point a,point b){if(a.num!=b.num) return a.num<b.num; return a.f>b.f;}int main(){ //freopen("data5.in","r",stdin); //freopen("data5.out","w",stdout); int n,a,b,cnt; while(scanf("%d",&n)==1) { cnt=0; for(int i=0;i<n;++i){ scanf("%d%d",&a,&b); p[cnt].num=a; p[cnt++].f=true; p[cnt].num=b; p[cnt++].f=false; } sort(p,p+cnt,cmp); int ans=0,tmp=0; for(int i=0;i<cnt;++i){ if(p[i].f){ tmp++; ans=max(ans,tmp); }else tmp--; } printf("%d\n",ans); } return 0;}
D、数独
好吧,其实以为E会爆零结果D爆了零--,其实就是一个精确覆盖的问题,我们可以采用DL算法(舞蹈链算法)+X算法(其实就是一个DFS),然后套个模板+乱搞=AC
如果是9*9的数独是可以直接DFS的!
给个直接DFS 9*9数独的:
#include <cstring>#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <vector>#include <map>#include <set>#include <queue>#include <climits>#include <utility>#include <stack>using namespace std;int n,M;int mp[25][25];bool visH[25][25];bool visL[25][25];bool visK[25][25][25];int f;void dfs(int pos){ if(pos==n*n) { f++; return; } int x=pos/n; int y=pos%n; if(!mp[x][y]) for(int i=1; i<=n; ++i) { if(!visH[x][i]&&!visL[y][i]&&!visK[x/M][y/M][i]) { mp[x][y]=i; visH[x][i]=true; visL[y][i]=true; visK[x/M][y/M][i]=true; dfs(pos+1); mp[x][y]=0; visH[x][i]=false; visL[y][i]=false; visK[x/M][y/M][i]=false; } } else dfs(pos+1); return;}int main(){ freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); while(scanf("%d",&n)==1) { M=int(sqrt(n)); memset(visH,false,sizeof(visH)); memset(visL,false,sizeof(visL)); memset(visK,false,sizeof(visK)); f=0; for(int i=0; i<n; ++i) { for(int j=0; j<n; ++j) { scanf("%d",&mp[i][j]); } } for(int i=0;i<n;++i){ for(int j=0;j<n;++j){ if(mp[i][j]){ visH[i][mp[i][j]]=true; visL[j][mp[i][j]]=true; visK[i/M][j/M][mp[i][j]]=true; } } } dfs(0); if(f)puts("Yes"); else puts("No"); } return 0;}
下面是本题DLX的代码:
#include <cstring>#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <vector>#include <strstream>#include <map>#include <set>#include <queue>#include <climits>#include <utility>using namespace std;struct DLX{ const static int maxn=20010; int n,sz; int S[maxn]; int row[maxn],col[maxn]; int L[maxn],R[maxn],U[maxn],D[maxn]; int ansd,ans[maxn]; void init(int n) { this->n=n; for(int i=0; i<=n; ++i) { U[i]=i; D[i]=i; L[i]=i-1; R[i]=i+1; } R[n]=0; L[0]=n; sz=n+1; memset(S,0,sizeof(S)); } void addRow(int r,vector <int> columns) { int first=sz; for(int i=0; i<columns.size(); ++i) { int c=columns[i]; L[sz]=sz-1; R[sz]=sz+1; D[sz]=c; U[sz]=U[c]; D[U[c]]=sz; U[c]=sz; row[sz]=r; col[sz]=c; S[c]++; sz++; } R[sz-1]=first; L[first]=sz-1; } #define FOR(i,A,s) for(int i=A[s];i!=s;i=A[i]) void remove (int c) { L[R[c]]=L[c]; R[L[c]]=R[c]; FOR(i,D,c) FOR(j,R,i) { U[D[j]]=U[j]; D[U[j]]=D[j]; --S[col[j]]; } } void restore(int c) { FOR(i,U,c) FOR(j,L,i) { ++S[col[j]]; U[D[j]]=j; D[U[j]]=j; } L[R[c]]=c; R[L[c]]=c; } bool dfs(int d) { if(R[0]==0) { ansd=d; return true; } int c=R[0]; FOR(i,R,0)if(S[i]<S[c])c=i; remove(c); FOR(i,D,c) { ans[d]=row[i]; FOR(j,R,i)remove(col[j]); if(dfs(d+1))return true; FOR(j,L,i)restore(col[j]); } restore(c); return false; } bool solve(vector <int>& v) { v.clear(); if(!dfs(0))return false; for(int i=0; i<ansd; ++i)v.push_back(ans[i]); return true; }};DLX slover;const int SLOT=0;const int ROW=1;const int COL=2;const int SUB=3;int encode(int a,int b,int c){ return a*16*16+b*16+c+1;}void decode(int code,int& a,int& b,int& c){ code--; c=code%16; code/=16; b=code%16; code/=16; a=code;}int puzzle[20][20];int main(){ //freopen("data1.in","r",stdin); //freopen("data1.out","w",stdout); for(int i=0; i<16; ++i) { for(int j=0; j<16; ++j) { scanf("%d",&puzzle[i][j]); } } slover.init(16*16*4); for(int r=0; r<16; ++r) { for(int c=0; c<16; ++c) { for(int v=0; v<16; ++v) { if(puzzle[r][c]==0||puzzle[r][c]==v+1) { vector <int> coulumns; coulumns.push_back(encode(SLOT,r,c)); coulumns.push_back(encode(ROW,r,v)); coulumns.push_back(encode(COL,c,v)); coulumns.push_back(encode(SUB,r/4*4+c/4,v)); slover.addRow(encode(r,c,v),coulumns); } } } } vector <int> ans; slover.solve(ans); for(int i=0; i<ans.size(); ++i) { int r,c,v; decode(ans[i],r,c,v); puzzle[r][c]=v+1; } for(int i=0; i<16; ++i) { for(int j=0; j<16; ++j) { if(j)putchar(' '); printf("%d",puzzle[i][j]); } puts(""); } return 0;}
E、简单的GCD
这一题是数论的题目,可以欧拉+容斥+搞搞搞=AC,其实最好的方法是利用莫比乌斯反演的结论(可以百度),其实简单来说就是,关键是求这个函数的值,求出来后容斥答案就出来了。
代码:
<span style="font-size:18px;">#include <cstring>#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <vector>#include <map>#include <set>#include <queue>#include <climits>#include <utility>using namespace std;const int MAXN = 1000000;int b,d,k;long long ans,cnt;bool vis[MAXN+5];int prime[MAXN+5],mu[MAXN+5];void init(){ memset(vis,false,sizeof(vis)); mu[1]=1; int tot=0; for(int i=2; i<=MAXN; i++) { if(!vis[i]) { prime[tot++]=i; mu[i]=-1; } for(int j=0; j<tot; j++) { if(i*prime[j]>MAXN) break; vis[i*prime[j]]=true; if( i%prime[j]==0) { mu[i*prime[j]]=0; break; } else { mu[i*prime[j]]=-mu[i]; } } }}int main(){ //freopen("data.in","r",stdin); //freopen("data.out","w",stdout); int T,cas=1; init(); scanf("%d",&T); while(T--) { scanf("%d%d%d",&b,&d,&k); b/=k; d/=k; if(b>d)swap(b,d); ans=0; cnt=0; for(int i=1; i<=b; ++i) { ans+=(long long)mu[i]*(b/i)*(d/i); cnt+=(long long)mu[i]*(b/i)*(b/i); } ans-=cnt/2; printf("Case %d: %lld\n",cas++,ans); } return 0;}</span>
0 0
- 2015 SWJTU 校集训队选拔赛 Ⅱ参考题解
- 2015苏州大学ACM-ICPC集训队选拔赛(1)题解
- BUAA集训队选拔赛部分简单题解
- 【题解】2016.5.8SWJTU校赛题解
- 北航2015集训队选拔赛解题报告
- BUAA集训队选拔赛
- 2015 SWJTU ACM Summer Training Final Assessment 1st 部分题解
- JXNU暑期选拔赛题解
- 蓝桥杯选拔赛题解
- 校第十六届大学生程序设计竞赛暨2016省赛集训队选拔赛1002
- 校第十六届大学生程序设计竞赛暨2016省赛集训队选拔赛1007
- 校第十六届大学生程序设计竞赛暨2016省赛集训队选拔赛(Problem E)
- 北航2016集训队选拔赛解题报告
- 2017年集训队第四场选拔赛Trainsorting
- 2013 CSU校队选拔赛(1) 部分题解
- 郑轻新生校赛和中工选拔赛题解
- 2015NCHU第一届ACM新生选拔赛A题题解
- 2015NCHU第一届ACM新生选拔赛B题题解
- 轮询与心跳机制
- 提高博客点击率的几个小方法
- 七牛李道兵:高可用可伸缩架构实用经验谈
- 不一样的倪张根
- modal的使用
- 2015 SWJTU 校集训队选拔赛 Ⅱ参考题解
- 15第四周实践——阅读程序
- 关于怎样选择人事考勤工资软件的一些建议
- 2014.9~2015.3 读书心得
- 练习题 求和 a+aa+aa+aa+aa (n个a)
- 百度一道笔试题(求n个整数连成一排组成的最小整数)
- 2015NCHU第一届ACM新生选拔赛F题题解
- mysql 重设密码
- 腾讯实习生【笔试--基础研究】