A.Smooth Visualization
简单模拟题,不多说了。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<set> #include<vector> #include<stack> #define mem(a,b) memset(a,b,sizeof(a)) #define FOR(a,b,i) for(i=a;i<=b;++i) #define For(a,b,i) for(i=a;i<b;++i) #define N 1000000007 using namespace std; inline void RD(int &ret) { char c; do { c=getchar(); } while(c<'0'||c>'9'); ret=c-'0'; while((c=getchar())>='0'&&c<='9') { ret=ret*10+(c-'0'); } } inline void OT(int a) { if(a>=10) { OT(a/10); } putchar(a%10+'0'); } int n; char s[105]; int ss[705]; int main() { int t; scanf("%d",&t); getchar(); while(t--) { gets(s); int l = strlen(s); int ll = 0; int ma = 0; int a = s[0] - '0'; ss[0] = a; ma = a; ll++; int b; for(int i=1;i<l;i++) { a = s[i-1] - '0'; b = s[i] - '0'; ma = max(ma,b); if(b == a) { ss[ll] = b; ll++; } if(b > a) { int c = a + 1; do { ss[ll] = c; c++; ll++; }while(c <= b); } if(b < a) { int c = a - 1; do { ss[ll] = c; c--; ll++; }while(c >= b); } } for(int i = ma;i >=1;i--) { for(int j=0;j<ll;j++) { if(i > ss[j]) printf("*"); else printf("+"); } printf("\n"); } } return 0; }
E.Social Holidaying
二分图匹配,题意是给你两个序列,要求A序列中最多有多少对数和为B序列中的数,且A序列中的数每个只能用一次,B序列的数可以无限次出现。
思路:可以将A序列中所有能组成的可能全都组合起来,如果B序列中有出现就开始搜索,把所有情况都搜出来。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<set> #include<vector> #include<stack> #include<map> #define mem(a,b) memset(a,b,sizeof(a)) #define FOR(a,b,i) for(i=a;i<=b;++i) #define For(a,b,i) for(i=a;i<b;++i) #define N 1000000007 using namespace std; inline void RD(int &ret) { char c; do { c=getchar(); } while(c<'0'||c>'9'); ret=c-'0'; while((c=getchar())>='0'&&c<='9') { ret=ret*10+(c-'0'); } } inline void OT(int a) { if(a>=10) { OT(a/10); } putchar(a%10+'0'); } map<long long,int>s; vector<int>p[1001]; int vis[1001],tmp[1001]; long long x[1001],y; int f(int j) { int i,q; for(i=0;i<p[j].size();++i) { q=p[j][i]; if(vis[q]==0) { vis[q]=1; if(tmp[q]==0||f(tmp[q])==1) { tmp[q]=j; return 1; } } } return 0; } int main() { int t,i,j,sum,n,m; scanf("%d",&t); while(t--) { s.clear(); scanf("%d%d",&n,&m); for(i=0;i<n;++i) { scanf("%lld",&x[i]); } for(i=0;i<m;++i) { scanf("%lld",&y); s[y]=1; } for(i=0;i<n;++i) { p[i].clear(); } sum=0; for(i=0;i<n;++i) { for(j=0;j<n;++j) { if(i==j) { continue; } if(s[x[i]+x[j]]==1) { p[i].push_back(j); } } } mem(tmp,0); for(i=0;i<n;++i) { mem(vis,0); if(f(i)==1) { sum++; } } printf("%d\n",sum/2); } return 0; }
G.Writings on the Wall
字符串问题,问的是前后两个字符串最多能重合部分几次。
方法有两种:kmp和hash
KMP写法:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<set> #include<vector> #include<stack> #define mem(a,b) memset(a,b,sizeof(a)) #define FOR(a,b,i) for(i=a;i<=b;++i) #define For(a,b,i) for(i=a;i<b;++i) //#define N 1000000007 using namespace std; inline void RD(int &ret) { char c; do { c=getchar(); } while(c<'0'||c>'9'); ret=c-'0'; while((c=getchar())>='0'&&c<='9') { ret=ret*10+(c-'0'); } } inline void OT(int a) { if(a>=10) { OT(a/10); } putchar(a%10+'0'); } #define N 50005 char a[N]; char b[N]; int next[N]; int l1,l2; void update() { next[0] = -1; int i=0,j=-1; while(i<l2) { while(j>=0&&b[i]!=b[j]) { j=next[j]; } i++; j++; next[i]=j; } } int main() { int t,i,j,ans; scanf("%d",&t); while(t--) { scanf("%s%s",a,b); l1=strlen(a); l2=strlen(b); update(); i=0; j=0; while(i<l1) { while(j>=0&&a[i]!=b[j]) { j=next[j]; } i++; j++; if(j==l2&&i<l1) { j=next[j]; } } ans=0; while(j>=0) { j=next[j]; ans++; } printf("%d\n",ans); } return 0; }
HASH写法:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<set> #include<vector> #include<stack> #include <queue> #include<map> #define mem(a,b) memset(a,b,sizeof(a)) #define FOR(a,b,i) for(i=a;i<=b;++i) #define For(a,b,i) for(i=a;i<b;++i) using namespace std; inline void RD(int &ret) { char c; do { c=getchar(); } while(c<'0'||c>'9'); ret=c-'0'; while((c=getchar())>='0'&&c<='9') { ret=ret*10+(c-'0'); } } inline void OT(int a) { if(a>=10) { OT(a/10); } putchar(a%10+'0'); } int main() { int i,j,l1,l2,t,sum; long long x,y,z; char a[50001],b[50001]; RD(t); while(t--) { scanf("%s%s",a,b); l1=strlen(a); l2=strlen(b); i=l1-1; j=0; z=1; x=0; y=0; sum=1; while(i>=0&&j<l2)//hash过程 { x+=z*(a[i]-'a'); z*=33; y*=33; y+=(b[j]-'a'); i--; j++; if(x==y) { sum++; } } printf("%d\n",sum); } return 0; }
H.Robotic Traceur
最短路,我们悲剧地居然一直TLE,后来才发现BFS,SPFA,甚至连暴搞都可以过。。。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<set> #include<vector> #include<stack> #include <queue> #include<map> #define mem(a,b) memset(a,b,sizeof(a)) #define FOR(a,b,i) for(i=a;i<=b;++i) #define For(a,b,i) for(i=a;i<b;++i) using namespace std; inline void RD(int &ret) { char c; do { c=getchar(); } while(c<'0'||c>'9'); ret=c-'0'; while((c=getchar())>='0'&&c<='9') { ret=ret*10+(c-'0'); } } inline void OT(int a) { if(a>=10) { OT(a/10); } putchar(a%10+'0'); } struct xl { double x,y; }v[1001]; double dis(int i, int j) { return sqrt((v[i].x-v[j].x)*(v[i].x-v[j].x)+(v[i].y-v[j].y)*(v[i].y-v[j].y)); } int main() { int t,n,s,tmp,i,id[1001],l[1001],w,res; double p,q; RD(t); while(t--) { scanf("%d%d%d%lf%lf",&n,&s,&tmp,&p,&q); p+=q; FOR(1,n,i) { scanf("%lf%lf",&v[i].x,&v[i].y); id[i]=-1; } id[s]=0; l[0]=s; w=1; res=0; while(res<w) { s=l[res]; FOR(1,n,i) { if(id[i]<0&&dis(s,i)<p+1e-6) { id[i]=id[s]+1; l[w++]=i; if(i==tmp) { break; } } } res++; } if(id[tmp]>=0) { printf("%d\n",id[tmp]); } else { printf("Impossible\n"); } } return 0; }
I.Shortest Leash
应该是一道dp题,它要求狗可以选择多个向量的正负方向走,问最远能与远点的距离为多少。。。
我是用随机算法过的,目的在于将所有的向量打乱,使其在加上向量时,能够会在一次中找到正解。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<set> #include<vector> #include<stack> #include<map> #define mem(a,b) memset(a,b,sizeof(a)) #define FOR(a,b,i) for(i=a;i<=b;++i) #define For(a,b,i) for(i=a;i<b;++i) using namespace std; struct xl { double x,y; } p[101],q,l,r; double dis(xl a) { return sqrt(a.x*a.x+a.y*a.y); } int main() { int t,i,j,z[101]; double ans; while(scanf("%d",&t)) { if(t==0) { break; } for(i=0; i<t; ++i) { scanf("%lf%lf",&p[i].x,&p[i].y); } ans=0; for(j=0;j<=10000;++j) { random_shuffle(p,p+t);//随机打乱数组 q.x=0; q.y=0; for(i=0; i<t; ++i) { l=q; r=q; l.x+=p[i].x; l.y+=p[i].y; r.x-=p[i].x; r.y-=p[i].y; if(dis(l)>dis(r)) { q=l; } else { q=r; } ans=max(ans,dis(q)); } } printf("%.3f\n",ans); } return 0; }