kuangbin带你飞 专题一

来源:互联网 发布:highcharts数据过密 编辑:程序博客网 时间:2024/05/18 00:59

kuangbin在vjudge上面挂了一些专题,感谢bin神带我飞~

Problem APOJ1321

中文题目 DFS 注意某一行可以不放棋子,因此需要在DFS函数后面加一个dfs(row+1,num)

#include<cstdio>#include<algorithm>#include<cstring>#include<string>#include<cmath>int visit[10],tot,n,k;int ch[10][10];void dfs(int row,int num){int j;if(num==k){tot++;return;}if(row>n)return;for(j=1;j<=n;j++)if(ch[row][j]&&!visit[j]){visit[j]=1;dfs(row+1,num+1);visit[j]=0;}dfs(row+1,num);return;}int main(){int i,j;char x;while(scanf("%d%d",&n,&k)!=EOF&&(n!=-1||k!=-1)){getchar();memset(ch,0,sizeof(ch));memset(visit,0,sizeof(visit));tot=0;for(i=1;i<=n;i++)for(j=1;j<=n;j++){scanf("%c",&x);if(x=='#')ch[i][j]=1;if(j==n)getchar();}dfs(1,0);printf("%d\n",tot);}return 0;} 

Problem B

POJ2251

三维的,共有6个方向,BFS,很水

#include <iostream>#include <queue>#include <cstring>#include<cstdio> using namespace std;int l,r,c;char g[31][31][31];int shift[6][3]={{-1,0,0},{1,0,0},{0,-1,0},{0,1,0},{0,0,-1},{0,0,1}};short flag[31][31][31];int s[3];int e[3];int min_path=0xffff;struct Point{int x;int y;int z;int step;};queue<Point> mq;bool inrange(int x,int y,int z){if(x>=0 && x<l && y>=0 && y<r && z>=0 && z<c)return true;elsereturn false;}void bfs(int x,int y,int z){Point p;p.x=x;p.y=y;p.z=z;p.step=0;flag[x][y][z]=1;mq.push(p);while(!mq.empty()){Point q = mq.front();mq.pop();if(q.x==e[0] && q.y==e[1] && q.z==e[2]){min_path = q.step;return;}for(int i=0;i<6;i++){Point m;m.x= q.x+shift[i][0];m.y= q.y+shift[i][1];m.z= q.z+shift[i][2];m.step =q.step+1;if(inrange(m.x,m.y,m.z) && g[m.x][m.y][m.z]!='#'  && flag[m.x][m.y][m.z]==0){flag[m.x][m.y][m.z]=1;mq.push(m);}}}}int main(){cin>>l;cin>>r;cin>>c;int i,j,k;while(l || r || c){min_path=0xffff;memset(g,0,sizeof(g));memset(flag,0,sizeof(flag));while(!mq.empty()){mq.pop();}for(i=0;i<l;i++){for(j=0;j<r;j++){getchar();for(k=0;k<c;k++){g[i][j][k]=getchar();if(g[i][j][k]=='S'){s[0]=i;s[1]=j;s[2]=k;}if(g[i][j][k]=='E'){e[0]=i;e[1]=j;e[2]=k;}}}getchar();}bfs(s[0],s[1],s[2]);if(min_path<0xffff)cout<<"Escaped in "<<min_path<<" minute(s)."<<endl;elsecout<<"Trapped!"<<endl;cin>>l;cin>>r;cin>>c;}}
Problem C

POJ3278

BFS水题 n经过多次+1or-1or*2后得到n

#include<cstdio>#include<algorithm>#include<queue>#include<cstring>using namespace std;int n,k,ans;int visit[200005];struct pos{int x;int t;};queue<pos>s;void bfs(int x){pos b;b.x=x;b.t=0;visit[x]=1;s.push(b);while(!s.empty()){pos m=s.front();s.pop();if(m.x==k){ans=m.t;return;}pos q;q.x=m.x-1;q.t=m.t+1;if(q.x>=0&&q.x<=100000&&visit[q.x]==0){visit[q.x]=1;s.push(q);}q.x=m.x+1;q.t=m.t+1;if(q.x>=0&&q.x<=100000&&visit[q.x]==0){visit[q.x]=1;s.push(q);}q.x=m.x*2;q.t=m.t+1;if(q.x>=0&&q.x<=100000&&visit[q.x]==0){visit[q.x]=1;s.push(q);}}}int main(){while(scanf("%d%d",&n,&k)!=EOF){memset(visit,0,sizeof(visit));while(!s.empty())s.pop();bfs(n);printf("%d\n",ans);}return 0;} 

Problem D

POJ3279

翻白块,开始想了好久,枚举第一行,后面的状态就可以确定了,因为上面一行没有翻过来的白块只有通过下一行才能翻过来

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#define INF 0x7fffffffusing namespace std;int n,m,mint;int dir_x[4]={0,0,1,-1};int dir_y[4]={1,-1,0,0};int map[16][16],t[16][16],ans[16][16],op[16][16];void operate(int x,int y){op[x][y]=1;t[x][y]^=1;for(int k=0;k<4;k++){int nowx=x+dir_x[k];int nowy=y+dir_y[k];if(nowx<1||nowy<1||nowx>n||nowy>m)continue;t[nowx][nowy]^=1; }}void solve(int x){int tot=0; memset(op,0,sizeof(op));for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)t[i][j]=map[i][j];for(int i=1;i<=m;i++)if((1<<(i-1))&x){tot++;if(tot>=mint)return;operate(1,m-i+1);}for(int i=2;i<=n;i++)for(int j=1;j<=m;j++){if(t[i-1][j]){tot++;if(tot>=mint)return;operate(i,j);}}for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(t[i][j])return;mint=tot;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)ans[i][j]=op[i][j];}int main(){int i,j;while(scanf("%d%d",&n,&m)!=EOF){for(i=1;i<=n;i++)for(j=1;j<=m;j++)scanf("%d",&map[i][j]);mint=INF-10;for(i=0;i<=((1<<m)-1);i++)solve(i);if(mint!=INF-10){for(i=1;i<=n;i++){for(j=1;j<m;j++)printf("%d ",ans[i][j]);printf("%d\n",ans[i][m]);}}else printf("IMPOSSIBLE\n");}return 0;} 
Problem E

POJ1426

一开始想的很复杂。。。后来发现只是个简单的DFS

#include<iostream>#include<cstdlib>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#include<queue>using namespace std; bool found; void DFS(unsigned __int64 t ,int n,int k) {     if(found)         return ;//如果已经发现了答案就没搜的必要了     if(t%n==0)     {//发现答案,输出,标记变量该true         printf("%I64u\n",t);        found=true;         return ;     }     if(k==19)//到第19层,回溯         return ;     DFS(t*10,n,k+1);    //搜索×10     DFS(t*10+1,n,k+1);    //搜索×10+1 } int main() {     int n;     while(cin>>n,n)     {         found=false;//标记变量,当为true代表搜到了题意第一的m         DFS(1,n,0);    //从1开始搜n的倍数,第三个参数代表搜的层数,当到第19层时返回(因为第20层64位整数存不下)    }     return 0;}

Problem F

POJ3126

素数打表DFS搞定

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<queue>using namespace std;int f[10000],prime[10000],visit[10000];int x,tag;struct state{int w[4];int t;};void isprime(){memset(prime,0,sizeof(prime));memset(f,0,sizeof(f));for(int i=2;i<=9999;i++){if(f[i]==0){for(int j=i+i;j<=9999;j+=i)f[j]=1;prime[i]=1;}}} void bfs(){int i,j;queue<state>s;state p; p.w[0]=x/1000;p.w[1]=(x-p.w[0]*1000)/100;p.w[3]=x%10;p.w[2]=(x-1000*p.w[0]-100*p.w[1]-p.w[3])/10;p.t=0;s.push(p);memset(visit,0,sizeof(visit));visit[x]=1;while(!s.empty()){state q,n;q=s.front();s.pop();int now=q.w[0]*1000+q.w[1]*100+q.w[2]*10+q.w[3];//printf("%d\n",now);//getchar();if(now==tag){printf("%d\n",q.t);return;}for(i=0;i<=3;i++)for(j=0;j<=9;j++){n=q;n.w[i]=j;n.t=q.t+1;int sum=n.w[0]*1000+n.w[1]*100+n.w[2]*10+n.w[3];if(!visit[sum]&&prime[sum]&&sum>1000){//printf("%d\n",sum);s.push(n);visit[sum]=1;}}}printf("Impossible\n");}int main(){int t,i;isprime();while(scanf("%d",&t)!=EOF){while(t--){scanf("%d%d",&x,&tag);bfs();} }return 0;} 

Problem G

POJ3087

模拟,如果回到初态说明不能成功,看到了一个特别短的代码,拿来引用了,很简洁,一看便懂

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>using namespace std;int main(){int i,n,t,j,m,k;char s1[201],s2[201],s[201],s0[201],stag[401];while(scanf("%d",&m)!=EOF){for(k=1;k<=m;k++){scanf("%d",&n);scanf("%s%s%s",s1,s2,stag);strcpy(s,s1);strcat(s,s2);strcpy(s0,s);for(t=0;strcmp(s,stag)!=0;t++){for(j=0;j<n;j++)s1[j]=s[j];for(i=0;i<n;i++,j++)s2[i]=s[j];for(i=0,j=0;i<n;i++,j+=2){s[j]=s2[i];s[j+1]=s1[i];}if(strcmp(s0,s)==0){t=-1;break;}}printf("%d %d\n",k,t);}}return 0;} 

Problem H
POJ3414
DFS六种可能性,用数组保存每次的操作代号最后输出,一开始用string直接保存的,结果TLE了。。。
#include<string>#include<cstring>#include<iostream>#include<cstdio>#include<algorithm>using namespace std;int a,b,c,res;char pa[10010],pp[10010];bool flag,vis[105][105];void dfs(int x,int y,int dep){if(dep>res)return;if(x==c||y==c){if(dep<res){flag=1;res=dep;for(int i=0;i<res;i++)pa[i]=pp[i];}return;}if(x<a&&!vis[a][y])//FILL 1{vis[a][y]=1;pp[dep]='f';dfs(a,y,dep+1);vis[a][y]=0;}if(y<b&&!vis[x][b])//FILL 2{vis[x][b]=1;pp[dep]='F';dfs(x,b,dep+1);vis[x][b]=0;}if(x>0&&!vis[0][y])//DROP 1{vis[0][y]=1;pp[dep]='d';dfs(0,y,dep+1);vis[0][y]=0;}if(y>0&&!vis[x][0])//DROP 2{vis[x][0]=1;pp[dep]='D';dfs(x,0,dep+1);vis[x][0]=0;}if(x>0&&y<b)//POUR(1,2){int t=min(x,b-y);if(!vis[x-t][y+t]){vis[x-t][y+t]=1;pp[dep]='p';dfs(x-t,y+t,dep+1);vis[x-t][y+t]=0;}}if(y>0&&x<a)//POUR(2,1){int t=min(y,a-x);if(!vis[x+t][y-t]){vis[x+t][y-t]=1;pp[dep]='P';dfs(x+t,y-t,dep+1);vis[x+t][y-t]=0;}}return;}int main(){int i;while(scanf("%d%d%d",&a,&b,&c)!=EOF){memset(vis,0,sizeof(vis));vis[0][0]=1;flag=0;res=0x7fffffff;dfs(0,0,0);if(flag){printf("%d\n",res);for(int i=0;i<res;i++){if(pa[i]=='f')printf("FILL(1)\n");if(pa[i]=='F')printf("FILL(2)\n");if(pa[i]=='d')printf("DROP(1)\n");if(pa[i]=='D')printf("DROP(2)\n");if(pa[i]=='p')printf("POUR(1,2)\n");if(pa[i]=='P')printf("POUR(2,1)\n");}}else printf("impossible\n");}return 0;}
Problem I
FZU2150
从两个地方放火,两处可以是同一地点,问最短需要多少时间才能让他们玩上XXOO游戏(可见 福州大学的Acmer啧啧啧啧)。。。。。。。
#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<queue>#define INF 0x7fffffffusing namespace std;int dir_x[4]={0,0,1,-1};int dir_y[4]={1,-1,0,0};int n,m,tmin,tmax;int map[11][11],vis[11][11];int visit[11][11][11][11]; struct state{int x,y;int t;//time};int inrange(int x,int y){if(x<1||x>n||y<1||y>m)return 1;return 0;}void bfs(int x1,int y1,int x2,int y2){queue<state>s;int i,j;for(i=1;i<=n;i++)for(j=1;j<=m;j++)vis[i][j]=map[i][j];state p;p.x=x1;p.y=y1;p.t=0;s.push(p);p.x=x2;p.y=y2;p.t=0;s.push(p);vis[x1][y1]=vis[x2][y2]=0;while(!s.empty()){state q;q=s.front();s.pop();tmax=q.t; for(i=0;i<4;i++){state now;now.x=q.x+dir_x[i];now.y=q.y+dir_y[i];now.t=q.t+1;if(!inrange(now.x,now.y)&&vis[now.x][now.y]){vis[now.x][now.y]=0;s.push(now);}}}for(i=1;i<=n;i++)for(j=1;j<=m;j++){if(vis[i][j])tmax=INF;}}int main(){ int i,j,t,p,q,k; char c; while(scanf("%d",&t)!=EOF) { for(k=1;k<=t;k++) { scanf("%d%d",&n,&m); getchar(); for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { cin>>c; if(c=='#') map[i][j]=1; else  map[i][j]=0; } } tmin=INF; memset(visit,0,sizeof(visit)); for(i=1;i<=n;i++) for(j=1;j<=m;j++) for(p=1;p<=n;p++) for(q=1;q<=m;q++) { if(map[i][j]&&map[p][q]&&!visit[p][q][i][j]) { visit[i][j][p][q]=1; bfs(i,j,p,q); tmin=min(tmin,tmax); } } if(tmin==INF) printf("Case %d: -1\n",k); else  printf("Case %d: %d\n",k,tmin); } } return 0;} 

Problem J
UVA11624
先BFS一次每一块着火的最段时间,再对JOE进行一次BFS,如果JOE到达某块的时间比它的着火时间短加入队列,
注意初始着火点可能有多个
#include<cstdio>#include<queue>#include<algorithm>#include<cstring>#include<string>#include<cmath>#include<iostream>#define INF 0x7fffffff-10 using namespace std;int dir_x[4]={1,-1,0,0};int dir_y[4]={0,0,1,-1};int c,r,fx[1000005],fy[1000005],jx,jy,cnt;int tim[1005][1005];bool vis[1005][1005];bool map[1005][1005];struct state{int x,y;int t;};int inrange(int x,int y){if(x>r||x<1||y>c||y<1)return 0;return 1;}void Fbfs(){int i,j;queue<state>s;state p;memset(vis,0,sizeof(vis));for(i=0;i<=cnt-1;i++){p.x=fx[i];p.y=fy[i];p.t=0;s.push(p);vis[fx[i]][fy[i]]=1; }while(!s.empty()){p=s.front();s.pop();for(i=0;i<4;i++){state now;now.x=p.x+dir_x[i];now.y=p.y+dir_y[i];if(inrange(now.x,now.y)&&!vis[now.x][now.y]&&!map[now.x][now.y]&&tim[now.x][now.y]>p.t+1){vis[now.x][now.y]=1;//if(time[now.x][now.y]>now.t)now.t=p.t+1;tim[now.x][now.y]=now.t;s.push(now);}} } }void Jbfs(){int i,j;state p;queue<state>s;p.x=jx;p.y=jy;p.t=0;s.push(p);memset(vis,0,sizeof(vis));vis[jx][jy]=1;while(!s.empty()){p=s.front();s.pop();if(p.x==r||p.y==c||p.x==1||p.y==1){printf("%d\n",p.t+1);return;}for(i=0;i<4;i++){state now;now.x=p.x+dir_x[i];now.y=p.y+dir_y[i];now.t=p.t+1;if(now.t<tim[now.x][now.y]&&!vis[now.x][now.y]&&inrange(now.x,now.y)&&!map[now.x][now.y]){vis[now.x][now.y]=1;s.push(now);}}}printf("IMPOSSIBLE\n");}int main(){int n,i,j;char ch;while(scanf("%d",&n)!=EOF){while(n--){cnt=0;scanf("%d%d",&r,&c);for(i=1;i<=r;i++)for(j=1;j<=c;j++){cin>>ch;tim[i][j]=INF; if(ch=='J'){jx=i;jy=j;map[i][j]=0;}if(ch=='F'){fx[cnt]=i;fy[cnt++]=j;map[i][j]=1;tim[i][j]=0;}if(ch=='#')map[i][j]=1;if(ch=='.')map[i][j]=0;}Fbfs();Jbfs();}}return 0;}
Problem K
POJ3984
结构体中用,pre变量保存当前点之前的位置,用数组模拟队列
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int dir_x[4]={0,0,1,-1};int dir_y[4]={1,-1,0,0};int visit[6][6];struct point{int x,y;int pre;//记录之前的位置 pre=previous}queue[100];bool inrange(int x,int y){if(x>4||x<0||y>4||y<0)return false;return true;}void print(int i){if(queue[i].pre!=-1){print(queue[i].pre);printf("(%d, %d)\n",queue[i].x,queue[i].y);}} void bfs(){int a,b;int front,rear;front=0;rear=1;queue[front].x=0;queue[front].y=0;queue[front].pre=-1;//(0, 0)之前的位置记为-1while(front<rear){for(int i=0;i<=3;i++){a=queue[front].x+dir_x[i];b=queue[front].y+dir_y[i];if(!inrange(a,b)||visit[a][b])continue;else {visit[a][b]=1;queue[rear].x=a;queue[rear].y=b;queue[rear].pre=front;rear++;}if(a==4&&b==4){printf("(0, 0)\n");print(front);printf("(4, 4)\n");}}front++;} } int main(){int i,j;while(scanf("%d",&visit[0][0])!=EOF){memset(visit,0,sizeof(visit));for(i=1;i<=4;i++)scanf("%d",&visit[0][i]);for(i=1;i<=4;i++)for(j=0;j<=4;j++)scanf("%d",&visit[i][j]);bfs();}return 0;} 
Problem L
HDU1241
连通块问题,DFS解决
#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>using namespace std;int dir_x[8]={0,0,1,-1,1,1,-1,-1};int dir_y[8]={1,-1,0,0,1,-1,1,-1};int map[105][105];int m,n;void dfs(int x,int y){map[x][y]=0;for(int i=0;i<=7;i++){int a=x+dir_x[i];int b=y+dir_y[i];if(a<1||b<1||b>n||a>m||map[a][b]==0)continue;elsedfs(a,b);}return;}int main(){int ans,i,j;char c;while(scanf("%d %d",&m,&n)!=EOF&&(m||n)){getchar();for(i=1;i<=m;i++){for(j=1;j<=n;j++){cin>>c;if(c=='@')map[i][j]=1;elsemap[i][j]=0;}}//for(i=1;i<=m;i++)//{//for(j=1;j<=n;j++)//printf("%d",map[i][j]);//printf("\n");//}ans=0;for(i=1;i<=m;i++)for(j=1;j<=n;j++)if(map[i][j]){dfs(i,j);ans++;}printf("%d\n",ans);}return 0;}

Problem M
HDU1495
倒可乐, 主要就是麻烦。。。分类讨论,结构体里每个变量都要赋值,找了好久的bug。。。
#include<cstdio>#include<iostream>#include<algorithm>#include<cstring> #include<queue>using namespace std;int visit[300][300];int f[3];struct state{int x[3];int step;//倒的次数; };queue<state>s;void bfs(){int i,j;state p;p.x[0]=f[0];p.x[1]=0;p.x[2]=0;p.step=0;s.push(p);while(!s.empty()){state q;q=s.front();s.pop();if((q.x[0]==f[0]/2&&q.x[1]==f[0]/2)||(q.x[0]==f[0]/2&&q.x[2]==f[0]/2)||(q.x[2]==f[0]/2&&q.x[1]==f[0]/2))//判断是否满足条件 {printf("%d\n",q.step);return;}for(i=0;i<=2;i++){state y;if(q.x[i]>0)//将i的可乐倒入j中 {for(j=0;j<=2;j++){if(i==j)continue;if(q.x[i]+q.x[j]>f[j]){y.x[i]=q.x[i]-(f[j]-q.x[j]);y.x[j]=f[j];y.x[3-i-j]=q.x[3-i-j];}else{y.x[i]=0;y.x[j]=q.x[i]+q.x[j];y.x[3-i-j]=q.x[3-i-j];}int a,b;a=y.x[1];b=y.x[2];if(a>=0&&b>=0&&a<=f[1]&&b<=f[2]&&visit[a][b]==0){visit[a][b]=1;y.step=q.step+1;s.push(y);}}}}}printf("NO\n");}int main(){while(scanf("%d%d%d",&f[0],&f[1],&f[2])!=EOF&&(f[0]||f[1]||f[2])){if(f[0]%2){printf("NO\n");continue;}if(f[1]==f[2]){printf("1\n");continue;}else{while(!s.empty())s.pop();memset(visit,0,sizeof(visit));visit[0][0]=true;bfs();}}return 0;}

Problem N
HDU2612
审题,两人时间的总和最少而不是俩人的时间只算一次,两次BFS即可,最后取最小时间的和
#include<cstdio>#include<iostream>#include<algorithm>#include<queue>#include<cstring> #define INF 0x7fffffffusing namespace std;int dir_x[4]={0,0,1,-1};int dir_y[4]={1,-1,0,0};char map[205][205];int ans1[205][205];int ans2[205][205]; int visit[205][205];int x1,x2,y1,y2,m,n,mint;struct state{int x,y;int step;};int inrange(int x,int y){if(x<1||x>n||y<1||y>m)return 0;return 1;}void bfs(int x,int y,int ans[205][205]){int i,j;memset(visit,0,sizeof(visit));memset(ans,0,sizeof(ans));queue<state>s;state p;p.x=x;p.y=y;p.step=0;s.push(p);visit[x][y]=1;while(!s.empty()){state q;q=s.front();s.pop();if(map[q.x][q.y]=='@'){ans[q.x][q.y]=q.step;}for(i=0;i<4;i++){state w;w.x=q.x+dir_x[i];w.y=q.y+dir_y[i];w.step=q.step+1;if(inrange(w.x,w.y)&&!visit[w.x][w.y]&&map[w.x][w.y]!='#'){s.push(w);visit[w.x][w.y]=1;}}}}int main(){int i,j;while(scanf("%d%d",&n,&m)!=EOF){getchar();for(i=1;i<=n;i++){for(j=1;j<=m;j++){cin>>map[i][j];if(map[i][j]=='Y'){x1=i;y1=j;}if(map[i][j]=='M'){x2=i;y2=j;}}}bfs(x1,y1,ans1);bfs(x2,y2,ans2);mint=INF;//for(i=1;i<=n;i++)//{//for(j=1;j<=m;j++)//{//cout<<ans2[i][j];//}//printf("\n");//}for(i=1;i<=n;i++)for(j=1;j<=m;j++){if(ans1[i][j]&&ans2[i][j]&&map[i][j]=='@')mint=min(mint,ans1[i][j]+ans2[i][j]);}printf("%d\n",mint*11);}return 0;}




0 0
原创粉丝点击