loli的混合算法测试
最近刚讲了最短路,说要考试我以为是考最短路,然而只有一道是最短路...
数据似乎有一点问题,不管了,反正手工测评都是对的,那现在就来看看题吧。
Balanced:(此处并没有网址)
题意概述:$n$ $(n<=50,000)$头牛排成一排,给定每头牛的位置,有两种种族,选出一个尽量长的区间使得这个区间内两种牛的数量相等。
首先可以想到枚举...前缀和...然而还是$O(N^2)$的复杂度,很显然是过不了的。思考一下前缀和的做法,用两个数组分别表示两种牛数量的前缀和。当$a[j]-a[i-1]=b[j]-b[i-1]$时,$x[j]-x[i]$就是一个合法的答案了。那对这个式子进行移项:$a[j]-b[j]=a[i-1]-b[i-1]$,所以可以再开一个数组表示$x[i]=a[i]-b[i]$,如果两个位置的$x$相同,就是一个合法的答案,而且区间越长答案一定更优,所以只需要保存每个$x$出现的第一次和最后一次位置,统计答案时取max就可以了。注意$x$数组可以出现负数,所以将整个数组同时加上$n$就可以避免负数了。
1 // shzr 2 3 # include <cstdio> 4 # include <iostream> 5 # include <algorithm> 6 # include <cstring> 7 8 using namespace std; 9 10 const int maxn=50009; 11 int n,s1[maxn],s2[maxn],ans,x[maxn],minn[maxn*3],maxx[maxn*3]; 12 struct co 13 { 14 int id,x; 15 }a[maxn]; 16 bool cmp(co a,co b) 17 { 18 return a.x<b.x; 19 } 20 21 int main() 22 { 23 scanf("%d",&n); 24 memset(minn,127,sizeof(minn)); 25 for (int i=1;i<=n;++i) 26 scanf("%d%d",&a[i].id,&a[i].x); 27 sort(a+1,a+1+n,cmp); 28 minn[0]=0; 29 for (int i=1;i<=n;++i) 30 { 31 if(a[i].id==0) s1[i]++; 32 if(a[i].id==1) s2[i]++; 33 s1[i]+=s1[i-1]; 34 s2[i]+=s2[i-1]; 35 x[i]=s1[i]-s2[i]; 36 minn[ x[i]+n+2 ]=min(minn[ x[i]+n+2 ],i); 37 maxx[ x[i]+n+2 ]=max(maxx[ x[i]+n+2 ],i); 38 } 39 for (int i=0;i<=2*n+2;++i) 40 { 41 if(maxx[i]==0||minn[i]>n) continue; 42 if(maxx[i]==minn[i]) continue; 43 ans=max(ans,a[ maxx[i] ].x-a[ minn[i]+1 ].x); 44 } 45 printf("%d",ans); 46 return 0; 47 }
找礼物:(此处依旧没有网址)
题意概述:
这道题目非常简单...根据距离排个序再扫一遍就做完了。还有一个问题是精度,因为保留四位小数且是截断小数,所以可以将距离乘上一万存进整型变量里。
1 //shzr 2 3 # include <cstdio> 4 # include <iostream> 5 # include <cmath> 6 # include <algorithm> 7 # include <cstring> 8 # include <string> 9 10 using namespace std; 11 12 int n,k; 13 long long x,y; 14 struct gif 15 { 16 string nam; 17 long long len; 18 int rk; 19 }a[100009]; 20 21 bool cmp(gif a,gif b) 22 { 23 if(a.len==b.len) 24 return a.rk<b.rk; 25 return a.len<b.len; 26 } 27 28 int main() 29 { 30 scanf("%d%d",&n,&k); 31 for (int i=1;i<=n;++i) 32 { 33 cin>>a[i].nam; 34 scanf("%lld%lld",&x,&y); 35 a[i].len=(long long)(sqrt(x*x+y*y)*10000); 36 a[i].rk=i; 37 } 38 sort(a+1,a+1+n,cmp); 39 int ans=0,pos=1; 40 long long x=0; 41 for (int i=1;i<=k-1;++i) 42 { 43 x=a[pos].len; 44 while(a[pos].len==x&&pos<=n) 45 pos++; 46 } 47 if(pos==n+1) 48 { 49 printf("555…"); 50 } 51 else 52 { 53 x=a[pos].len; 54 for (int i=pos;i<=n;++i) 55 { 56 if(a[i].len==x) ans++; 57 else break; 58 } 59 printf("%lld %d\n",x/10000,ans); 60 for (int i=pos;i<=n;++i) 61 { 62 if(a[i].len==x) cout<<a[i].nam<<endl; 63 else break; 64 } 65 } 66 return 0; 67 }
Game:(还是没有网址)
和四子连棋有一点像的状压搜索题。
1 //shzr 2 3 # include <cstdio> 4 # include <iostream> 5 6 using namespace std; 7 8 const int dx[]={-1,0,0,1}; 9 const int dy[]={0,1,-1,0}; 10 int no,beg,en,x,h=1,t=0; 11 bool vis[700000]; 12 int q[6000000]; 13 int b[6000000]; 14 int a[5][5]; 15 16 void ad(int x) 17 { 18 for (int i=4;i>=1;--i) 19 for (int j=4;j>=1;--j) 20 { 21 a[i][j]=x%2; 22 x/=2; 23 } 24 } 25 26 int pul() 27 { 28 int ans=0; 29 for (int i=1;i<=4;++i) 30 for (int j=1;j<=4;++j) 31 ans=(ans<<1)+a[i][j]; 32 return ans; 33 } 34 35 int bfs(int beg) 36 { 37 vis[beg]=true; 38 q[++t]=beg; 39 b[t]=0; 40 while (h<=t) 41 { 42 x=q[h]; 43 if(x==en) return b[h]; 44 ad(x); 45 for (int i=1;i<=4;++i) 46 for (int j=1;j<=4;++j) 47 for (int z=0;z<4;++z) 48 { 49 int xx=i+dx[z]; 50 int yy=j+dy[z]; 51 if(xx<1||xx>4||yy<1||yy>4) 52 continue; 53 if(a[xx][yy]==a[i][j]) continue; 54 swap(a[xx][yy],a[i][j]); 55 no=pul(); 56 if(vis[no]==false) 57 { 58 vis[no]=true; 59 q[++t]=no; 60 b[t]=b[h]+1; 61 } 62 swap(a[xx][yy],a[i][j]); 63 } 64 h++; 65 } 66 return -1; 67 } 68 69 int main() 70 { 71 for (int i=1;i<=4;++i) 72 for (int j=1;j<=4;++j) 73 { 74 scanf("%1d",&x); 75 beg=(beg<<1)+x; 76 } 77 for (int i=1;i<=4;++i) 78 for (int j=1;j<=4;++j) 79 { 80 scanf("%1d",&x); 81 en=(en<<1)+x; 82 } 83 printf("%d",bfs(beg)); 84 return 0; 85 }
Car的旅行路线:https://www.luogu.org/problemnew/show/P1027
一直觉得很麻烦不想做的题出现在了考试里...那只好做一做了。其实就是把所有边连上以后跑最短路。
1 //shzr 2 3 # include <cstdio> 4 # include <iostream> 5 # include <cmath> 6 # include <cstring> 7 # include <queue> 8 9 using namespace std; 10 11 int co,s,t,A,B,firs[500],h=0; 12 struct nod 13 { 14 int x,y; 15 }a[500]; 16 bool vis[500]; 17 double d[500]; 18 typedef pair<double,int> pii; 19 priority_queue <pii,vector<pii>,greater<pii> > q; 20 struct edge 21 { 22 int nex,too; 23 double len; 24 }g[500000]; 25 26 void add(int x,int y,double c) 27 { 28 g[++h].too=y; 29 g[h].nex=firs[x]; 30 firs[x]=h; 31 g[h].len=c; 32 g[++h].too=x; 33 g[h].nex=firs[y]; 34 firs[y]=h; 35 g[h].len=c; 36 } 37 38 void find_four(int i) 39 { 40 nod A=a[4*i+1],B=a[4*i+2],C=a[4*i+3],D; 41 long long la,lb,lc; 42 la=(B.x-C.x)*(B.x-C.x)+(B.y-C.y)*(B.y-C.y); 43 lb=(A.x-C.x)*(A.x-C.x)+(A.y-C.y)*(A.y-C.y); 44 lc=(A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y); 45 if(la+lb==lc) 46 { 47 D.x=B.x-C.x+A.x; 48 D.y=B.y-C.y+A.y; 49 } 50 if(la+lc==lb) 51 { 52 D.x=-B.x+C.x+A.x; 53 D.y=-B.y+C.y+A.y; 54 } 55 if(lb+lc==la) 56 { 57 D.x=B.x+C.x-A.x; 58 D.y=B.y+C.y-A.y; 59 } 60 a[4*i+4]=D; 61 } 62 63 void dij(int s) 64 { 65 memset(d,127,sizeof(d)); 66 d[s]=0; 67 q.push(make_pair(d[s],s)); 68 int j,beg; 69 while (q.size()) 70 { 71 beg=q.top().second; 72 q.pop(); 73 if(vis[beg]) continue; 74 vis[beg]=true; 75 for (int i=firs[beg];i;i=g[i].nex) 76 { 77 j=g[i].too; 78 if(d[beg]+g[i].len>=d[j]) continue; 79 d[j]=d[beg]+g[i].len; 80 q.push(make_pair(d[j],j)); 81 } 82 } 83 } 84 85 int main() 86 { 87 scanf("%d%d%d%d",&s,&t,&A,&B); 88 for (int i=0;i<s;++i) 89 { 90 scanf("%d%d%d%d%d%d",&a[4*i+1].x,&a[4*i+1].y,&a[4*i+2].x,&a[4*i+2].y,&a[4*i+3].x,&a[4*i+3].y); 91 scanf("%d",&co); 92 find_four(i); 93 for (int m=1;m<=4;++m) 94 for (int n=m+1;n<=4;++n) 95 add(4*i+m,4*i+n,co*sqrt((a[4*i+m].x-a[4*i+n].x)*(a[4*i+m].x-a[4*i+n].x)+(a[4*i+m].y-a[4*i+n].y)*(a[4*i+m].y-a[4*i+n].y))); 96 for (int j=1;j<=4;++j) 97 for (int k=1;k<=4*i;++k) 98 add(4*i+j,k,sqrt((a[4*i+j].x-a[k].x)*(a[4*i+j].x-a[k].x)+(a[4*i+j].y-a[k].y)*(a[4*i+j].y-a[k].y))*t); 99 } 100 for (int i=1;i<=4;++i) 101 { 102 add(0,(A-1)*4+i,0); 103 add(s*4+5,(B-1)*4+i,0); 104 } 105 dij(0); 106 printf("%.1lf",d[s*4+5]); 107 return 0; 108 }
---shzr