[kuangbin带你飞]专题一 简单搜索
454 / 1008 Problem A POJ 1321 棋盘问题
d.在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
s.dfs
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; char cb[10][10];//棋盘 int col[10];//标记当前列是否有棋子 int ans,n,k;//ans 记录方案总数 void dfs(int row,int sum){//行,已放置的总数 if(sum==k){//已摆放的棋子总数 等于 k ans++; return; } int i,j; for(i=row;i<n;i++){//遍历行,从没有放置棋子的row行开始遍历 for(j=0;j<n;j++){//遍历列,从第一列开始遍历 if(cb[i][j]=='#'&&!col[j]){//棋盘区域,并且当前列没有棋子 col[j]=1; dfs(i+1,sum+1);//在下一行中寻找放置棋子的位置 col[j]=0;//取消标记 } } } } int main(){ int i; while(~scanf("%d%d",&n,&k)){ if(n==-1&&k==-1)break; ans=0;//方案总数 memset(col,0,sizeof(col));//标记初始化 memset(cb,'\0',sizeof(cb));//棋盘初始化 for(i=0;i<n;i++)scanf("%s",cb[i]); dfs(0,0);//0行,已放置总数0个 printf("%d\n",ans); } return 0; }
328 / 854 Problem B POJ 2251 Dungeon Master
335 / 1101 Problem C POJ 3278 Catch That Cow
d.起始位置N,目标位置K。
3种操作,当前+1、当前-1、当前*2
s.bfs
#include<iostream> #include<stdio.h> #include<string.h> #include<queue> using namespace std; const int Ma=100000; bool vis[Ma+1];//标记访问 int ti[Ma+1];//记录时间 int n,k;//农夫、牛的位置 void bfs(){//广搜 int i,now,temp; queue<int>q; memset(ti,0,sizeof(ti)); memset(vis,false,sizeof(vis));//初始化都未被访问 q.push(n);//初始位置入队 vis[n]=true; while(!q.empty()){ now=q.front(); q.pop(); if(now==k){//判断在这,如果抓到牛了 printf("%d\n",ti[k]); return; } for(i=1;i<=3;i++){//枚举下一步的三种移动方案,x-1、x+1、2*x switch(i){ case 1:temp=now-1;break; case 2:temp=now+1;break; case 3:temp=now+now;break; } if(!vis[temp]&&temp>=0&&temp<=Ma){//当前位置未被访问,且位置合法 vis[temp]=1;//标记访问 ti[temp]=ti[now]+1;//时间=当前位置时间+1 q.push(temp);//位置入队 } } } } int main(){ while(~scanf("%d%d",&n,&k)){ bfs(); } return 0; }
161 / 503 Problem D POJ 3279 Fliptile
247 / 526 Problem E POJ 1426 Find The Multiple
d.给出n,求一个n的倍数,这个倍数只含0或1
s.bfs
#include<iostream> #include<stdio.h> #include<queue> using namespace std; int main(){ __int64 t,t2; int n,i; while(~scanf("%d",&n)&&n!=0){ queue<__int64>q;//队列定义在循环内,每次就不用清空了 q.push(1);//首位必须为1 while(!q.empty()){ t=q.front(); q.pop(); if(t%n==0){//找到了倍数,输出 printf("%I64d\n",t);break; } for(i=0;i<=1;i++){// 每次最后一位 加个0 或者 加个1 t2=t*10+i; q.push(t2); } } } return 0; }
205 / 330 Problem F POJ 3126 Prime Path
d.一个4位的素数到另外一个4位的素数,每次只能改变一位,改变后也必须是素数,求最少需要的步数。
s.bfs
#include<iostream> #include<stdio.h> #include<string.h> #include<queue> #include<math.h> using namespace std; const int Ma=11000;//覆盖所有的四位数 bool mark[Ma];//标记素数 int s[Ma];//记录步数 bool f[Ma];//标记访问 void sieve_prime(){//素数筛法 memset(mark,true,sizeof(mark)); mark[0]=mark[1]=false; int k=sqrt(Ma),i,j; for(i=2;i<k;i++) if(mark[i]) for(j=i*i;j<Ma;j+=i) mark[j]=false; } int change(int x,int i,int j){//x的第i位数字 变为j if(i==1)return j*1000+(x%1000);//依次改变1-4位的数字 if(i==2)return (x/1000)*1000+j*100+x%100; if(i==3)return (x/100)*100+j*10+x%10; if(i==4)return (x/10)*10+j; } int main(){ sieve_prime();//先求出素数 int t,x,y,ans,now,temp,i,j,flag;// scanf("%d",&t);//测试用例 while(t--){ memset(f,false,sizeof(f));//初始未访问 ans=-1; flag=0;//标记是否找到路径 scanf("%d%d",&x,&y);//起点 和终点 queue<int>q;//队列定义在循环内,不用每次用的时候清空了 q.push(x);//x入队 now=s[x]=0;//初始当前步数、x的步数 为0 f[x]=true;//x标记为访问 while(!q.empty()){ now=q.front(); q.pop(); if(now==y){//如果到达终点 flag=1;//标记找到路径 break;//退出循环 } for(i=1;i<=4;i++){//第几位 for(j=0;j<=9;j++){//变成几 if(!(j==0&&i==1)){//首位不能变为0 temp=change(now,i,j); if(!mark[temp]||f[temp])continue;//不是素数,或已经访问过 s[temp]=s[now]+1;//下个位置的步数为 当前步数+1 f[temp]=true;//标记temp为访问 q.push(temp);//temp 入队 } } } } if(flag)printf("%d\n",s[y]); else printf("Impossible\n"); } return 0; }
143 / 305 Problem G POJ 3087 Shuffle'm Up
129 / 347 Problem H POJ 3414 Pots
141 / 463 Problem I FZU 2150 Fire Game
134 / 710 Problem J UVA 11624 Fire!
255 / 399 Problem K POJ 3984 迷宫问题
196 / 276 Problem L HDU 1241 Oil Deposits
177 / 408 Problem M HDU 1495 非常可乐
d. S 可乐的体积 , N 和 M是两个杯子的容量。这三个容器可以来回倒,求平分可乐的最少次数。
s.bfs
#include<iostream> #include<stdio.h> #include<string.h> #include<queue> using namespace std; int vist[105][105][105],a,b,c;//a b c->S 可乐的体积 , N 和 M是两个杯子的容量 struct node { int a,b,c;//分别表示可乐瓶子,杯子1,杯子2它们里面的可乐体积 int step;//步数 }; int sum=0; void bfs() { queue<node>q; memset(vist,0,sizeof(vist)); node p1; p1.a=a; p1.b=0; p1.c=0; p1.step=0; q.push(p1); vist[p1.a][0][0]=1; while(!q.empty()) { p1=q.front(); q.pop(); if((p1.a==a/2&&p1.b==a/2)||(p1.a==a/2&&p1.c==a/2)||(p1.b==a/2&&p1.c==a/2)) { printf("%d\n",p1.step); return; } // node p2; if(p1.a!=0) {//a倒入b if(p1.a>b-p1.b) { p2.a=p1.a-(b-p1.b); p2.b=b; p2.c=p1.c; p2.step=p1.step+1; } else { p2.a=0; p2.b=p1.b+p1.a; p2.c=p1.c; p2.step=p1.step+1; } if(!vist[p2.a][p2.b][p2.c]) { vist[p2.a][p2.b][p2.c]=1; q.push(p2); } } if(p1.a!=0) {//a倒入c if(p1.a>c-p1.c) { p2.a=p1.a-(c-p1.c); p2.b=p1.b; p2.c=c; p2.step=p1.step+1; } else { p2.a=0; p2.b=p1.b; p2.c=p1.c+p1.a; p2.step=p1.step+1; } if(!vist[p2.a][p2.b][p2.c]) { vist[p2.a][p2.b][p2.c]=1; q.push(p2); } } if(p1.b!=0) {//b倒入a if(p1.b>a-p1.a) { p2.b=p1.b-(a-p1.a); p2.a=a; p2.c=p1.c; p2.step=p1.step+1; } else { p2.b=0; p2.a=p1.a+p1.b; p2.c=p1.c; p2.step=p1.step+1; } if(!vist[p2.a][p2.b][p2.c]) { vist[p2.a][p2.b][p2.c]=1; q.push(p2); } } if(p1.b!=0) {//b倒入c if(p1.b>c-p1.c) { p2.b=p1.b-(c-p1.c); p2.a=p1.a; p2.c=c; p2.step=p1.step+1; } else { p2.b=0; p2.a=p1.a; p2.c=p1.c+p1.b; p2.step=p1.step+1; } if(!vist[p2.a][p2.b][p2.c]) { vist[p2.a][p2.b][p2.c]=1; q.push(p2); } } if(p1.c!=0) {//c倒入a if(p1.c>a-p1.a) { p2.c=p1.c-(a-p1.a); p2.a=a; p2.b=p1.b; p2.step=p1.step+1; } else { p2.c=0; p2.a=p1.a+p1.c; p2.b=p1.b; p2.step=p1.step+1; } if(!vist[p2.a][p2.b][p2.c]) { vist[p2.a][p2.b][p2.c]=1; q.push(p2); } } if(p1.c!=0) {//c倒入b if(p1.c>b-p1.b) { p2.c=p1.c-(b-p1.b); p2.a=p1.a; p2.b=b; p2.step=p1.step+1; } else { p2.c=0; p2.a=p1.a; p2.b=p1.b+p1.c; p2.step=p1.step+1; } if(!vist[p2.a][p2.b][p2.c]) { vist[p2.a][p2.b][p2.c]=1; q.push(p2); } } } printf("NO\n"); } int main() { while(~scanf("%d%d%d",&a,&b,&c)) { if(a==0&&b==0&&c==0){ break; } if(a%2==1) { printf("NO\n"); continue; } bfs(); } return 0; }
182 / 577 Problem N HDU 2612 Find a way