noip2017题解
没有正解,都是我的暴力
T1
枚举两个金币个数
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int a,b,ans; int c[10000]; int main() { scanf("%d%d",&a,&b); if(a>b)swap(a,b); for(int i=0;i<100;i++) { for(int j=0;j<=100;j++) { c[a*i+b*j]=true; } } int js=0; for(int i=0;i<=a*b;i++) { if(c[i])js=0; else ans=i,js++; } cout<<ans<<endl; return 0; }
T2
以下是我打的部分分代码
队列模拟做标记
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int T; int js,L; bool flag; char fzd[10]; char a[10],b[10],c[10],d[10],e[10],f[10]; int get() { if(fzd[2]=='1') return 0; int x=0,Len=strlen(fzd); for(int i=4; i<Len; i++) { if(fzd[i]<'0'||fzd[i]>'9') break; x=x*10+fzd[i]-'0'; } return x; } int main() { scanf("%d",&T); while(T--) { scanf("%d",&L); cin>>fzd; flag=true; js=0; int p; p=get();//p是给的复杂度 for(int i=1; i<=L; i++) { cin>>a; if(a[0]=='F') { cin>>b>>c>>d; int cc,dd; if(c[0]=='n') cc=1000; else cc=c[0]-'0'; if(d[0]=='n') dd=1000; else dd=d[0]-'0'; if(dd-cc>=100&&flag)js++; } } if(js==p) printf("Yes\n"); else printf("No\n"); } return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int T; int t,flag,ans,L; int s[30],q[120]; char fzd[10]; char a[10],b[10],c[10],d[10],e[10]; int get() { if(fzd[2]=='1') return 0; int x=0,Len=strlen(fzd); for(int i=4;i<Len;i++) { if(fzd[i]<'0'||fzd[i]>'9') break; x=x*10+fzd[i]-'0'; } return x; } int main() { scanf("%d",&T); while(T--) { scanf("%d",&L); cin>>fzd; int p,js;p=get(); ans=0;flag=0;t=0; for(int i=1;i<=L;i++) { cin>>a; if(a[0]=='F') { cin>>b>>c>>d; int cc=0,dd=0; if(c[0]=='n') cc=10000; else { int lc;lc=strlen(c); for(int j=0;j<lc;j++) cc=cc*10+c[j]-'0'; } if(d[0]=='n') dd=10000; else { int ld;ld=strlen(d); for(int j=0;j<ld;j++) dd=dd*10+d[j]-'0'; } if(cc>dd) flag++,s[b[0]-'a']=true; if(dd>=cc&&!flag) { if(dd-cc>=100) q[++t]=b[0]-'a'; ans=max(ans,t); } } if(a[0]=='E') { if(s[q[t]]) s[q[t]]=0,flag--; t--; } } if(ans==p) printf("Yes\n"); else printf("No\n"); } return 0; }
然而还没有a
// luogu-judger-enable-o2 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int L,T; int t,f,flag,ans; int q[120],s[120],vis[30],in[30]; char fzd[10]; char a[10],b[10],c[10],d[10],e[10]; int get() { if(fzd[2]=='1') return 0; int x=0,Len=strlen(fzd); for(int i=4;i<Len;i++) { if(fzd[i]<'0'||fzd[i]>'9') break; x=x*10+fzd[i]-'0'; } return x; } int main() { scanf("%d",&T); while(T--) { scanf("%d",&L);cin>>fzd; int p,js;p=get();ans=js=0;f=t=0; memset(vis,0,sizeof(vis)); memset(in,0,sizeof(in)); for(int i=1;i<=L;i++) { cin>>a; if(a[0]=='F') { cin>>b>>c>>d; if(vis[b[0]-'a']) { f=true; break; } vis[b[0]-'a']=true; int cc,dd;cc=dd=0; if(c[0]=='n') cc=10000; else { int lc=strlen(c); for(int j=0;j<lc;j++) cc=cc*10+c[j]-'0'; } if(d[0]=='n') dd=10000; else { int ld=strlen(d); for(int j=0;j<ld;j++) dd=dd*10+d[j]-'0'; } q[++t]=b[0]-'a'; if(cc>dd) s[b[0]-'a']=true,flag++; if(cc<=dd&&!flag) { if(dd-cc>=100) in[b[0]-'a']=true,js++; ans=max(ans,js); } } if(a[0]=='E') { vis[q[t]]=false;if(s[q[t]]) s[q[t]]=0,flag--; if(in[q[t]]) in[q[t]]=false,js--; t--; } } if(t||f) { printf("ERR\n"); continue; } if(ans==p) printf("Yes\n"); else printf("No\n"); } return 0; }
T3
spfa算出最短路,dfs找最短路和最短路+k之间的路径的条数
#include<iostream> #include<cstdio> #include<queue> #include<cstring> #include<algorithm> #define N 200008 using namespace std; int T,L,R,Ans; int n,m,k,p; int sumedge; int head[N],vis[N],dis[N]; queue<int>q; struct Edge { int x,y,z,nxt; Edge(int x=0,int y=0,int z=0,int nxt=0): x(x),y(y),z(z),nxt(nxt){} }edge[N<<1]; void add(int x,int y,int z) { edge[++sumedge]=Edge(x,y,z,head[x]); head[x]=sumedge; } void clear() { memset(vis,0,sizeof(vis)); memset(head,0,sizeof(head)); sumedge=0; } void spfa() { memset(vis,0,sizeof(vis)); memset(dis,0x3f,sizeof(dis)); while(!q.empty())q.pop(); dis[1]=0;vis[1]=true;q.push(1); while(!q.empty()) { int now=q.front();q.pop();vis[now]=false; for(int i=head[now];i;i=edge[i].nxt) { int v=edge[i].y; if(dis[v]>dis[now]+edge[i].z) { dis[v]=dis[now]+edge[i].z; if(!vis[v]) { vis[v]=true; q.push(v); } } } } } void dfs(int now,int g) { if(g>R) return; if(now==n) { Ans=(Ans%p+1%p)%p; } for(int i=head[now];i;i=edge[i].nxt) { int v=edge[i].y; dfs(v,g+edge[i].z); } } int main() { scanf("%d",&T); while(T--) { scanf("%d%d%d%d",&n,&m,&k,&p); clear();Ans=0; for(int i=1;i<=m;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); add(x,y,z); } spfa();L=dis[n];R=dis[n]+k; dfs(1,0); printf("%d\n",Ans); } return 0; }
T1
Int相乘能爆,要开long long
#include<iostream> #include<queue> #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> #define N 1020 #define LL long long using namespace std; int T; LL n,h,r; int flag; int vis[N]; queue<int>q; struct B { LL x,y,z; //忘开LL }a[N]; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } bool cmp(B a,B b) { return a.z<b.z; } double dis(int x,int y) { LL X;X=(a[x].x-a[y].x)*(a[x].x-a[y].x); LL Y;Y=(a[x].y-a[y].y)*(a[x].y-a[y].y); LL Z;Z=(a[x].z-a[y].z)*(a[x].z-a[y].z); return sqrt(X+Y+Z); } void BFS(int now) { memset(vis,0,sizeof(vis)); while(!q.empty()) q.pop(); vis[now]=true;q.push(now); while(!q.empty()) { int now=q.front();q.pop(); if(a[now].z+r>=h) { flag=true; break; } for(int i=1;i<=n;i++) { if(vis[i]) continue; if(dis(i,now)>1.*2*r) continue; q.push(i);vis[i]=true; } } } int main() { T=read(); while(T--) { flag=false; n=read();cin>>h>>r; for(int i=1;i<=n;i++) { a[i].x=read();a[i].y=read();a[i].z=read(); } sort(a+1,a+n+1,cmp); for(int i=1;i<=n;i++) { if(a[i].z-r<=0)BFS(i); if(flag) { printf("Yes\n"); break; } } if(!flag) printf("No\n"); } return 0; }
T2
20%是树 枚举起点+dfs
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,m,ans,res; int d[10][10]; void dfs(int now,int sc,int pre) { for(int i=1;i<=n;i++) { if(i==now||i==pre||d[now][i]==0) continue; ans=ans+d[now][i]*sc; dfs(i,sc+1,now); } return ; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); d[x][y]=d[y][x]=z; } res=1000000000; for(int i=1;i<=n;i++) { ans=0; dfs(i,1,0); res=min(res,ans); } printf("%d\n",res); return 0; }
70% dfs。
枚举起点和每次要开拓的边。
枚举边就枚举要开拓的点,再枚举这个点有哪个点开拓来。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,m; int tmp,ans; int d[12][12],Len[12]; void dfs(int now,int scr) { if(now==n) { tmp=min(tmp,scr); return ; } if(scr>=ans) return ; for(int i=1;i<=n;i++) { if(Len[i]) continue; for(int j=1;j<=n;j++) { if(d[i][j]==2147483640||Len[j]==0) continue; Len[i]=Len[j]+1; dfs(now+1,scr+Len[j]*d[i][j]); Len[i]=0; } } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(i==j) continue; d[i][j]=2147483640; } } for(int i=1;i<=m;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); d[x][y]=d[y][x]=min(d[x][y],z); } ans=2147483645; for(int i=1;i<=n;i++) { memset(Len,0,sizeof(Len)); Len[i]=1;tmp=2147483640; dfs(1,0); ans=min(ans,tmp); } cout<<ans<<endl; return 0; }
T3
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; int n,m,q; int a[3002][3003]; int qx[30004],qy[30004]; int main() { scanf("%d%d%d",&n,&m,&q); for(int i=1;i<=q;i++) scanf("%d%d",&qx[i],&qy[i]); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { a[i][j]=(i-1)*m+j; } } for(int i=1;i<=q;i++) { int x=qx[i],y=qy[i]; int tmp=a[x][y]; printf("%d\n",tmp); for(int j=y;j<m;j++) a[x][j]=a[x][j+1]; for(int j=x;j<n;j++) a[j][m]=a[j+1][m]; a[n][m]=tmp; } return 0; }