算法竞赛入门经典 笔记(1)
P144 UVa12657 移动盒子 Boxes in a Line
#include<cstdio> typedef long long LL; LL n,m; LL l[100010],r[100010],p;//双向链表 LL case1;//记录这是第几种情况 int main() { LL t,ans,i,a,x,y,k; while(scanf("%lld%lld",&n,&m)==2) { p=0;//记录现在顺序是正的还是反的 for(i=1;i<=n;i++) { l[i]=i-1;r[i]=i+1; } for(i=1;i<=m;i++) { scanf("%lld",&a); if(a==4) p=!p; else { if(a!=3&&p) a=3-a;//忘了加导致错,因为如果p不为0表示顺序是颠倒的 //而我们只是记录了p,并没有实际颠倒过来,因此p不为0时操作左侧实际要右侧,操作右侧实际要操作左侧 scanf("%lld%lld",&x,&y); if(a==1) { if(x==l[y]) continue;//忘了加,其实可以不加 r[l[x]]=r[x]; l[r[x]]=l[x]; r[l[y]]=x; l[x]=l[y]; r[x]=y; l[y]=x; } if(a==2) { if(x==r[y]) continue;//忘了加,其实可以不加 r[l[x]]=r[x]; l[r[x]]=l[x]; l[r[y]]=x; r[x]=r[y]; l[x]=y; r[y]=x; } if(a==3) { if(r[y]==x) { t=y; y=x; x=t; } if(r[x]==y) { r[l[x]]=y; l[r[y]]=x; l[y]=l[x]; r[x]=r[y]; l[x]=y; r[y]=x; } //曾经忽略了x、y相邻时交换的特殊情况,就是上面的情况,导致错误 else { r[l[x]]=y; r[l[y]]=x; l[r[x]]=y; l[r[y]]=x; t=r[x]; r[x]=r[y]; r[y]=t; t=l[x]; l[x]=l[y]; l[y]=t; } } } } t=0; ans=0; if(p==0) { for(i=1;i<=n;i++) if(l[i]==0) { k=i; while(k!=n+1) { t=not t; if(t) ans+=k; k=r[k]; } break; } } else { for(i=1;i<=n;i++) if(r[i]==n+1) { k=i; while(k!=0) { t=not t; if(t) ans+=k; k=l[k]; } } } printf("Case %lld: %lld\n",++case1,ans); } return 0; }
P138 UVa212 医院设备利用 Use of Hospital Facilities
#include<iostream> #include<cstring> //出过错:病人要去的恢复室,是根据做完手术那一刻编号最小的空的恢复室决定的 //而不是到之后编号最小的空的恢复室 //出过错:那个the patient with the lower number指的是在门牌号小的手术室做手术的患者。那个number竟然指的门牌号!http://www.cnblogs.com/xienaoban/p/6798078.html #include<string> #include<queue> using namespace std; struct Patient { string name; int room,b1,e1,bed,b2,e2;//分别记录病人的手术室,手术开始时间,手术结束时间,恢复室,恢复开始时间,恢复结束时间 int t1,t2;//分别记录病人的手术和恢复时间 }pt[110]; int rm[11],bd[31];//记录room和bed的使用时间 struct Query { int room,end,ptn; Query(){} Query(int b,int c,int d) { room=b;end=c;ptn=d; } friend bool operator<(const Query&a,const Query& b) { return (a.end>b.end)||(a.end==b.end&&a.room>b.room)||(a.end==b.end&&a.room==b.room&&a.ptn>b.ptn); }//这个排序对于病人做手术、从手术出来、恢复的排序都有效 }; int q_num=0; priority_queue<Query> q1; priority_queue<Query> q2;//记录病人从手术室出来的顺序(就是pop的顺序)、结束时间(end)、做手术的房间(room) bool boo[31]; int n,m,T,t1,t2,t3,k,maxt; int main() { int i; while(scanf("%d%d%d%d%d%d%d",&n,&m,&T,&t1,&t2,&t3,&k)==7)//出过错:当成单组数据了 { memset(boo,0,sizeof(boo)); memset(rm,0,sizeof(rm)); memset(bd,0,sizeof(bd)); maxt=-1; T=60*T; for(i=1;i<=k;i++) { cin>>pt[i].name; scanf("%d%d",&pt[i].t1,&pt[i].t2); } Query qt,qt2; for(i=1;i<=min(n,k);i++) { q1.push(Query(i,pt[i].t1+T,i)); pt[i].b1=T; pt[i].room=i; } for(i=min(n,k)+1;i<=k;i++) { qt=q1.top(); q1.pop(); rm[qt.room]+=pt[qt.ptn].t1; pt[qt.ptn].e1=qt.end; q1.push(Query(qt.room,qt.end+t2+pt[i].t1,i)); pt[i].b1=qt.end+t2; pt[i].room=qt.room; q2.push(Query(qt.room,qt.end,qt.ptn)); } while(!q1.empty()) { qt=q1.top(); q1.pop(); rm[qt.room]+=pt[qt.ptn].t1; pt[qt.ptn].e1=qt.end; q2.push(Query(qt.room,qt.end,qt.ptn)); } // while(!q2.empty()) // { // qt=q2.top(); // q2.pop(); // printf("%d %d %d\n",qt.end,qt.ptn,pt[qt.ptn].t2+qt.end); // } // for(i=1;i<=n;i++) // printf("%d %d\n",i,rm[i]); // for(i=1;i<=k;i++) // printf("%d %d %d\n",pt[i].room,pt[i].b1,pt[i].e1); while(!q2.empty()) { qt=q2.top(); q2.pop(); while(!q1.empty()) { qt2=q1.top(); if(qt2.end+t3<=qt.end)//出过错:没加等号 { q1.pop(); pt[qt2.ptn].e2=qt2.end; boo[qt2.room]=false; bd[qt2.room]+=pt[qt2.ptn].t2; maxt=max(maxt,qt2.end); } else break; } for(i=1;i<=m;i++) if(boo[i]==false) { boo[i]=true; q1.push(Query(i,qt.end+pt[qt.ptn].t2+t1,qt.ptn)); pt[qt.ptn].b2=qt.end+t1; pt[qt.ptn].bed=i; break; } } while(!q1.empty()) { qt2=q1.top(); q1.pop(); maxt=max(maxt,qt2.end); bd[qt2.room]+=pt[qt2.ptn].t2; pt[qt2.ptn].e2=qt2.end; } printf(" Patient Operating Room Recovery Room\n"); printf(" # Name Room# Begin End Bed# Begin End\n"); printf(" ------------------------------------------------------\n"); for(i=1;i<=k;i++) printf("%2d %-10s%2d %2d:%02d %2d:%02d %2d %2d:%02d %2d:%02d\n",i,pt[i].name.c_str(),pt[i].room,pt[i].b1/60,pt[i].b1%60,pt[i].e1/60,pt[i].e1%60,pt[i].bed,pt[i].b2/60,pt[i].b2%60,pt[i].e2/60,pt[i].e2%60); printf("\nFacility Utilization\nType # Minutes % Used\n"); printf("-------------------------\n"); maxt-=T; for(i=1;i<=n;i++) printf("Room %2d %4d %5.2f\n",i,rm[i],(double)rm[i]*100/maxt); for(i=1;i<=m;i++) printf("Bed %2d %4d %5.2f\n",i,bd[i],(double)bd[i]*100/maxt); printf("\n");//注意:不要少空行 } return 0; }
P148 UVa 679 小球下落 Dropping Balls
记在滚某个球时,滚到节点i的次数为a[i]
显然,如果a[i]为奇数,那么a[i*2]为(a[i]+1)/2,a[i*2+1]为(a[i]-1)/2(如果直接整除的话也可以表示为a[i]/2)
(原因是a[i]为奇数,那么前面a[i]-1次必定是左右各走(a[i]-1)/2次,这一次必定是向左走)
如果a[i]为偶数,那么a[i*2]=a[i*2+1]=a[i]/2
而且如果a[i]为奇数,那么下一步会往a[i*2]走
如果a[i]为偶数,那么下一步会往a[i*2+1]走
显然a[1]就是题目中的I,那么现在可以求出叶子节点了
这再次说明了写程序不如多想想
P154
对比:
#include<cstdio> int b[100000001]; int *a; int main() { int i; a=(int*)&b; *a=29; for(int i=1;i<=100000000;i++) *(a+i)=(*(a+i-1)+*(a+i-2))*2%10000000; printf("%d",*(a+10000000)); }
#include<cstdio> int b[100000001]; int *a; int main() { int i; a=(int*)&b; *a=29; for(i=1;i<=100000000;i++) b[i]=(b[i-1]+b[i-2])*2%10000000; printf("%d",b[10000000]); }内存池
P160 UVa 297 四分树 Quadtrees
输出测试数据(?):
#include<cstdio> #include<cstdlib> #include<cstring> #include<ctime> int a[33][33]; void print(int l1,int l2,int w) { bool b1=false,b2=false; int i,j; if(w==1) { if(a[l1][l2]==0) printf("e"); else printf("f"); return; } for(i=0;i<w;i++) for(j=0;j<w;j++) { if(a[l1+i][l2+j]==0) b1=true; if(a[l1+i][l2+j]==1) b2=true; if(b1&&b2) goto haha; } haha: if(b1&&(!b2)) printf("e"); else if((!b1)&&b2) printf("f"); else { printf("p"); print(l1+w/2,l2,w/2); print(l1,l2,w/2); print(l1,l2+w/2,w/2); print(l1+w/2,l2+w/2,w/2); } } int main() { int i,j; srand(time(0)); printf("1\n"); memset(a,0,sizeof(a)); for(i=1;i<=32;i++) for(j=1;j<=32;j++) a[i][j]=rand()%2; print(1,1,32); printf("\n"); for(i=1;i<=32;i++) for(j=1;j<=32;j++) a[i][j]=rand()%2; print(1,1,32); }程序:
#include<cstdio> #include<cstring> int ans;//答案 int buf[35][35];//记录draw出来的正方形 char s[2000];//曾经未注意,开太小了,实际上最大远远大于32*32,因为一个2*2的格子,最多占5个字符而不是4个,更多的类似 int p,n;//当前字符序号 //把s绘制到以(r,c)为左上角,边长为w的buf中 void draw(const char* s,int r,int c,int w) { char ch=s[p++]; int i,j; if(ch=='p') { draw(s,r+w/2,c,w/2); draw(s,r,c,w/2); draw(s,r,c+w/2,w/2); draw(s,r+w/2,c+w/2,w/2); //举例:最开始0-31,0-31 /*分开: 1:16-31,0-15 2:0-15,0-15 3:0-15,16-31 4:16-31,16-31 */ } else if(ch=='f') for(i=0;i<w;i++) for(j=0;j<w;j++) if(buf[r+i][c+j]==0) { ans++; buf[r+i][c+j]=1; } } int main() { int i; scanf("%d",&n); for(i=1;i<=n;i++) { ans=0; //memset(s,0,sizeof(s)); memset(buf,0,sizeof(buf)); scanf("%s",s); p=0; draw(s,0,0,32); scanf("%s",s); p=0; draw(s,0,0,32); printf("There are %d black pixels.\n",ans); } return 0; }