TEST2018.4.21(Noip2015提高组Day1)
为2019级lizw0520zzh的学生献上福利!!!
T1 神奇的幻方:
模拟题,很简单,按照题目描述进行模拟就行了,只是判断条件有点多,细心就行了。
用pos[i][0]表示i的行数,用pos[i][1]表示i的列数(这样好判断一些),mapp[][]记录幻方(mapp防止与map重名)。
代码(我一开始竟然调了好久?!):
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=45; int mapp[N][N]; int pos[N*N][2]; int n; void print() { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) printf("%d ",mapp[i][j]); printf("\n"); } } int main() { //freopen("magic.in","r",stdin); //freopen("magic.out","w",stdout); scanf("%d",&n); pos[1][0]=1;pos[1][1]=(n+1)/2;mapp[pos[1][0]][pos[1][1]]=1; for(int i=2;i<=n*n;i++) { if(pos[i-1][0]==1&&pos[i-1][1]!=n) pos[i][0]=n,pos[i][1]=pos[i-1][1]+1,mapp[pos[i][0]][pos[i][1]]=i; else if(pos[i-1][1]==n&&pos[i-1][0]!=1) pos[i][1]=1,pos[i][0]=pos[i-1][0]-1,mapp[pos[i][0]][pos[i][1]]=i; else if(pos[i-1][0]==1&&pos[i-1][1]==n) pos[i][1]=n,pos[i][0]=pos[i-1][0]+1,mapp[pos[i][0]][pos[i][1]]=i; else if(pos[i-1][0]!=1&&pos[i-1][1]!=n) { if(!mapp[pos[i-1][0]-1][pos[i-1][1]+1]) pos[i][0]=pos[i-1][0]-1,pos[i][1]=pos[i-1][1]+1; else pos[i][0]=pos[i-1][0]+1,pos[i][1]=pos[i-1][1]; mapp[pos[i][0]][pos[i][1]]=i; } //print(); } print(); return 0; }
T2 信息传递:
2015的题真的很水。
核心就是找出最小环的长度。
扫描二维码关注公众号,回复:
56265 查看本文章
这道题做法很多,我的思路是删去入度为0的点,然后直接dfs跑一遍就行。其他方法大家可以百度。
友情链接:水友gay周的博客(标准做法) 顺便说一下rancy是他的女朋友。
代码(宇宙最简):
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<queue> using namespace std; const int N=200000+233; int n,in[N],a[N]; bool vis[N]; bool del() { bool re=false; for(int i=1;i<=n;i++) if(!in[i]&&!vis[i]) re=true,in[a[i]]--,a[i]=-1,vis[i]=true; return re; } int dfs(int now,const int o) { if(now==o&&vis[o]) return 0; vis[now]=true; return dfs(a[now],o)+1; } int main() { //freopen("message.in","r",stdin); //freopen("message.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",a+i); in[a[i]]++; } int ans=N+10; while(del()); for(int i=1;i<=n;i++) if(!vis[i]) ans=min(ans,dfs(i,i)); printf("%d",ans); return 0; }
大家有空可以尝试并查集做法。
T3 斗地主:
输了地主赢了人生的我(隔壁赢了地主输了人生的佘刀已经die了)。
就是模拟题(Noip2015模拟题真的多)
大家可以认真思考下最优策略,然后dfs顺子的出牌方式就行了,具体方法大家自行百度吧。
多组数据忘了初始化ans的我已经哭晕在厕所了。。。我的AK啊!
代码(绝对良心):
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define maxx(a,b) a>b?a:b #define minn(a,b) a<b?a:b using namespace std; int T,n,a[20],ans; void init() { memset(a,0,sizeof(a)); for(int num,opt,i=1;i<=n;i++) { scanf("%d%d",&num,&opt); if(num==0) a[14]++; if(num==1) a[12]++; if(num==2) a[13]++; if(num>=3) a[num-2]++; } } void solve(int x) { if(x>ans) return; int s1,s2,s3,s4; s1=s2=s3=s4=0; for(int i=1;i<=14;i++) { if(a[i]==1) s1++; if(a[i]==2) s2++; } for(int i=1;i<=14;i++) { if(a[i]==4) { s4++; if(s1>=2) s1-=2; else if(s2>=2) s2-=2; else if(s2>=1) s2-=1; } } for(int i=1;i<=14;i++) { if(a[i]==3) { s3++; if(s1>=1) s1-=1; else if(s2>=1) s2-=1; } } ans=min(ans,x+s1+s2+s3+s4); for(int i=1;i<=8;i++) { int j; for(j=i;j<=12;j++) { a[j]--; if(a[j]<0) break; if(j-i>=4) solve(x+1); } if(j==13) j--; while(j>=i) a[j--]++; } for(int i=1;i<=10;i++) { int j; for(j=i;j<=12;j++) { a[j]-=2; if(a[j]<0) break; if(j-i>=2) solve(x+1); } if(j==13) j--; while(j>=i) a[j--]+=2; } for(int i=1;i<=11;i++) { int j; for(j=i;j<=12;j++) { a[j]-=3; if(a[j]<0) break; if(j-i>=1) solve(x+1); } if(j==13) j--; while(j>=i) a[j--]+=3; } } int main() { //freopen("landlords.in","r",stdin); //freopen("landlords.out","w",stdout); scanf("%d%d",&T,&n); while(T--) { ans=23; init(); solve(0); printf("%d\n",ans); } return 0; }最后祝大家早日AK!