[kuangbin带你飞]专题一 简单搜索
[kuangbin带你飞]专题一 简单搜索
算法:sf / / 错误点:w // 注意细节:xj
第一题 POJ 1321
sf:dfs xj:在于状态函数的标记和取消
这里输入使用了 ch = getchar() 抓取字符。
因为要找出所有方法数,所以暴力dfs就可以了。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n,k,ck;
char ch;
bool h[10],l[10],fk[10][10];
long long ans;
void init(){
memset(h,false,sizeof h);
memset(l,false,sizeof l);
memset(fk,false,sizeof fk);
ans=0;ck=0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++){
ch=getchar();
if(ch=='\n') ch=getchar();
if(ch=='#') fk[i][j]=true,ck++;
}
}
void dfs(int a,int b,int c){
if(c==k) ans++;
else{
for(int i=a+1;i<n;i++){
if(h[i]) continue;
for(int j=0;j<n;j++){
if(l[j]) continue;
if(fk[i][j]){
h[i]=true;l[j]=true;
dfs(i,j,c+1);
h[i]=false;l[j]=false;
}
}
}
}
}
int main()
{
while(cin>>n>>k){
if(n==-1&&k==-1) break;
init();
for(int i=0;i<n&&ck>=k;i++)
for(int j=0;j<n&&ck>=k;j++)
if(fk[i][j]){
h[i]=true;l[j]=true;
dfs(i,j,1);
h[i]=false;l[j]=false;
ck--;
}
cout<<ans<<endl;
}
return 0;
}
第二题POJ - 2251
sf:bfs xj:在于三维的迷宫 用三维状态函数
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int l,r,c;
char ch;
bool fk[31][31][31];
bool cp;
struct node{
int z,x,y;
int cc;
};
node k,j;
queue<node> q;
void init(){
cp=false;
memset(fk,false,sizeof fk);
for(int z=1;z<=l;z++)
for(int x=1;x<=r;x++)
for(int y=1;y<=c;y++){
ch=getchar();
while(ch=='\n') ch=getchar();
if(ch=='S') k.cc=0,k.x=x,k.y=y,k.z=z;
if(ch=='E') j.x=x,j.y=y,j.z=z;
if(ch=='E'||ch=='.') fk[z][x][y]=true;
}
}
bool check(int z,int x,int y){
if(z<1||z>l) return false;
if(x<1||x>r) return false;
if(y<1||y>c) return false;
if(fk[z][x][y]) return true;
return false;
}
int main()
{
while(cin>>l>>r>>c){
if(l==0&&r==0&&c==0) break;
init();
q.push(k);
while(!q.empty()){
node n = q.front();q.pop();
if(n.x==j.x&&n.z==j.z&&n.y==j.y) {cout<<"Escaped in "<<n.cc<<" minute(s)."<<endl;cp=true;break;}
if(check(n.z-1,n.x,n.y)) {node m = n;m.z--;m.cc++;q.push(m);fk[n.z-1][n.x][n.y]=false;}
if(check(n.z+1,n.x,n.y)) {node m = n;m.z++;m.cc++;q.push(m);fk[n.z+1][n.x][n.y]=false;}
if(check(n.z,n.x-1,n.y)) {node m = n;m.x--;m.cc++;q.push(m);fk[n.z][n.x-1][n.y]=false;}
if(check(n.z,n.x+1,n.y)) {node m = n;m.x++;m.cc++;q.push(m);fk[n.z][n.x+1][n.y]=false;}
if(check(n.z,n.x,n.y-1)) {node m = n;m.y--;m.cc++;q.push(m);fk[n.z][n.x][n.y-1]=false;}
if(check(n.z,n.x,n.y+1)) {node m = n;m.y++;m.cc++;q.push(m);fk[n.z][n.x][n.y+1]=false;}
}
while(!q.empty()) q.pop();
if(!cp) cout<<"Trapped!"<<endl;
}
return 0;
}
sf:bfs 难点:在于判断 当超过目标不需要 +1
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int M = 1e5;
int n,k;
int cp[M+5];
queue<int> q;
int main()
{
memset(cp,-1,sizeof cp);
cin>>n>>k;
cp[n]=0;
q.push(n);
while(!q.empty()){
int m=q.front();q.pop();
if(m==k) break;
if(m*2<=M&&cp[m*2]<0) {q.push(m*2);cp[m*2]=cp[m]+1;}
if(m+1<=k&&cp[m+1]<0) {q.push(m+1);cp[m+1]=cp[m]+1;}
if(m>=1&&cp[m-1]<0) {q.push(m-1);cp[m-1]=cp[m]+1;}
}
cout << cp[k] << endl;
return 0;
}
sf:暴力枚举第一行的情况(用2进制) 然后每下一行的操作取决于上一行是否存在1
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define inf 1e9
long long cnt,tt;
int n,m;
char ch;
int ans[20][20],akb[20][20];
bool fk[20][20],jk[20][20];
void init(){
cnt=inf;
memset(jk,false,sizeof jk);
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++){
ch=getchar();
while(ch=='\n'||ch==' ') ch=getchar();
if(ch=='1') jk[i][j]=true;
}
}
void check(int i,int j){
if(fk[i][j]) fk[i][j]=false;
else fk[i][j]=true;
if(fk[i+1][j]) fk[i+1][j]=false;
else fk[i+1][j]=true;
if(fk[i+1][j+1]) fk[i+1][j+1]=false;
else fk[i+1][j+1]=true;
if(fk[i+1][j-1]) fk[i+1][j-1]=false;
else fk[i+1][j-1]=true;
if(fk[i+2][j]) fk[i+2][j]=false;
else fk[i+2][j]=true;
}
void check2(int i,int j){
if(fk[i][j]) fk[i][j]=false;
else fk[i][j]=true;
if(fk[i][j+1]) fk[i][j+1]=false;
else fk[i][j+1]=true;
if(fk[i][j-1]) fk[i][j-1]=false;
else fk[i][j-1]=true;
if(fk[i+1][j]) fk[i+1][j]=false;
else fk[i+1][j]=true;
}
bool go(){
for(int i=1;i<m;i++)
for(int j=1;j<=n;j++)
if(fk[i][j]){
check(i,j);
tt++;if(tt>=cnt) return false;
ans[i+1][j]++;
}
for(int j=1;j<=n;j++) if(fk[m][j]) return false;
return true;
}
void solve(int x){
tt=0;memset(ans,0,sizeof ans);
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
fk[i][j]=jk[i][j];
for(int i=0;i<n;i++) if((1<<i)&x) {check2(1,i+1);ans[1][i+1]++;tt++;if(tt>=cnt) return ;}
if(go()){
cnt=tt;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++) akb[i][j]=ans[i][j];
}
}
int main()
{
cin>>m>>n;
init();
for(int i=0;i<(1<<n);i++) solve(i);
if(cnt==inf) cout<<"IMPOSSIBLE"<<endl;
else {
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++)
cout<<akb[i][j]<<' ';
cout<<endl;
}
}
return 0;
}
sf:bfs 余数*10+0/1 或者 直接dfs
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
int n;
bool fk[201];
struct node{
int a;
string str;
};
node k;
int main()
{
while(cin>>n&&n!=0){
memset(fk,false,sizeof fk);
k.a = 1%n;k.str = "1";fk[k.a] = true;
queue<node> q;q.push(k);
while(!q.empty()){
node p = q.front();q.pop();
int a = p.a;string str = p.str;
if(a==0) {cout<<str<<endl;break;}
else{
node m;
m.a = a*10%n, m.str = str + "0";
if(!fk[m.a]) q.push(m),fk[m.a] = true;
m.a = (a*10+1)%n, m.str = str + "1";
if(!fk[m.a]) q.push(m),fk[m.a] = true;
}
}
}
return 0;
}
#include <iostream>
#include <cstdio>
using namespace std;
int n,flag;
void dfs(unsigned long long a,int step){
if(flag||step==50) return ;
if(a%n==0) {flag = 1;printf("%I64u\n",a);return ;}
else{
dfs(a*10,step+1);
dfs(a*10+1,step+1);
}
}
int main()
{
while(~scanf("%d",&n)&&n){
flag = 0;
dfs(1,0);
}
return 0;
}
sf:求质数 + bfs
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
int n,m;
int y[5];
int ans[10000];
queue<int> q;
bool check(int x){
for(int i=2;i*i<=x;i++) if(x%i==0) return false;
return true;
}
void go(int x){
for(int i=1;i<=4;i++){
y[i]=x%10;
x/=10;
}
}
void dfs(){
memset(ans,-1,sizeof ans);
q.push(n);ans[n]=0;
while(!q.empty()){
int x = q.front();q.pop();
if(x==m) break;
go(x);
int z = x - y[1];
for(int i=0;i<=9;i++) if(i!=y[1]&&ans[z+i]<0&&check(z+i)) q.push(z+i),ans[z+i]=ans[x]+1;
z = x - y[2]*10;
for(int i=0;i<=9;i++) if(i!=y[2]&&ans[z+i*10]<0&&check(z+i*10)) q.push(z+i*10),ans[z+i*10]=ans[x]+1;
z = x - y[3]*100;
for(int i=0;i<=9;i++) if(i!=y[3]&&ans[z+i*100]<0&&check(z+i*100)) q.push(z+i*100),ans[z+i*100]=ans[x]+1;
z = x - y[4]*1000;
for(int i=1;i<=9;i++) if(i!=y[4]&&ans[z+i*1000]<0&&check(z+i*1000)) q.push(z+i*1000),ans[z+i*1000]=ans[x]+1;
}
while(!q.empty()) q.pop();
}
int main()
{
int _;cin>>_;
while(_--){
cin>>n>>m;
dfs();
if(ans[m]>=0) cout<<ans[m]<<endl;
else cout<<"Impossible"<<endl;
}
return 0;
}
#include <iostream>
#include <cstring>
#include <math.h>
#include <queue>
using namespace std;
const int M = 1e5;
int ans;
bool ip[M+5];
int dp[M+5];
void isPrime(int n){
memset(ip,true,sizeof ip);ip[0] = false,ip[1] = false;
double db = n;
int m = floor(sqrt(db));
for(int i = 2;i<=m;i++) if(ip[i])
for(int j = i;j*i <=n; j++) ip[j*i] = false;
}
void init(){
ans = 0;
memset(dp,-1,sizeof dp);
}
int bfs(int a,int b){
queue<int> q;
q.push(a);dp[a] = 0;
while(!q.empty()){
int p = q.front();q.pop();
if(p == b) return dp[b];
else{
int x1 = p%10, y1 = p %100, z1 = p%1000;
int x = p - x1, y = p - y1 + x1 , z = p - z1 + y1 ;
for(int i=0;i<=9;i++){
int h = x+i;if(dp[h]==-1&&ip[h]) dp[h] = dp[p] + 1,q.push(h);
h = y+i*10;if(dp[h]==-1&&ip[h]) dp[h] = dp[p] + 1,q.push(h);
h = z+i*100;if(dp[h]==-1&&ip[h]) dp[h] = dp[p] + 1,q.push(h);
if(i==0) continue;
h = z1 + i*1000;if(dp[h]==-1&&ip[h]) dp[h] = dp[p] + 1,q.push(h);
}
}
}
return dp[b];
}
int main()
{
int _;cin>>_;
isPrime(M);
while(_--){
init();
int a,b;cin>>a>>b;
cout<<bfs(a,b)<<endl;
}
return 0;
}
质数单个求就是直接从2到sqrt(n)进行求余
bool check(int x){
for(int i=2;i*i<=x;i++) if(x%i==0) return false;
return true;
}
筛选方法的话:就是从2到sqrt(n)取i,范围(最大到n),然后进行向后乘i
void isPrime(int n){
memset(ip,true,sizeof ip);ip[0] = false,ip[1] = false;
double db = n;
int m = floor(sqrt(db));
for(int i = 2;i<=m;i++) if(ip[i])
for(int j = i;j*i <=n; j++) ip[j*i] = false;
}
sf:简单模拟题 用到 set 进行排除string重复,然后使用string的assign函数进行取子串,
#include <iostream>
#include <set>
using namespace std;
int x,cnt,tt,y=1;
string a,b,c,d;
set<string> s;
void slove(){
s.clear();cnt = 0;
cin>>x>>a>>b>>c;
d=c;
while(1){
tt = 0;
for(int i=0;i<x;i++) d[tt++]=b[i],d[tt++]=a[i];cnt++;
if(d==c) {cout<<y++<<" "<<cnt<<endl;break;}
if(s.count(d)==1) {cout<<y++<<" -1"<<endl;break;}
a.assign(d,0,x);
b.assign(d,x,x);
s.insert(d);
}
}
int main()
{
int _;cin>>_;
while(_--){
slove();
}
return 0;
}
sf:bfs 难点在于 两个水杯容量x,y 与得水量z的关系 z必须能除掉 gcd(x,y);
gcd函数,switch函数都是优美代码
int gcd(int a,int b) {return b==0?a:gcd(b,a%b);}
#include <iostream>
#include <cstring>
#include <string.h>
#include <cstdio>
#include <queue>
using namespace std;
int a,b,c;
bool vis[101][101];
struct node{
int x,y,num;
}k;
struct mm{
int number,pre;
}akb[12000];
int gcd(int a,int b) {return b==0?a:gcd(b,a%b);}
void show(int x){
if(akb[x].pre==-1) return ;
show(akb[x].pre);
switch(akb[x].number){
case 1:puts("FILL(1)");break;
case 2:puts("FILL(2)");break;
case 3:puts("POUR(1,2)");break;
case 4:puts("POUR(2,1)");break;
case 5:puts("DROP(1)");break;
case 6:puts("DROP(2)");
}
}
void bfs(){
k.x = 0 , k.y = 0 , k.num = 0;
akb[0].pre = -1;
vis[0][0]=true;
queue<node> q;
q.push(k);
while(!q.empty()){
node o = q.front();q.pop();
int x , y ,num;
for(int i=1;i<=6;i++){
if(i==5) x = 0 , y = o.y ;
else if(i==6) x = o.x , y = 0;
else if(i==1) x = a , y = o.y;
else if(i==2) x = o.x , y = b;
else if(i==3){
x = o.x - min(o.x , b - o.y);
y = o.y + min(o.x , b - o.y);
}
else{
x = o.x + min(o.y , a - o.x);
y = o.y - min(o.y , a - o.x);
}
if(vis[x][y]) continue;
vis[x][y]=true;
num = o.num + 1;
akb[x*101+y].number = i;
akb[x*101+y].pre = o.x*101 + o.y;
if(x == c || y == c) {cout<<num<<endl;show(x*101+y);return;}
node f;f.x=x,f.y=y,f.num=num;
q.push(f);
}
}
}
int main()
{
cin>>a>>b>>c;
memset(vis,false,sizeof vis);
if(c%gcd(a,b)) puts("impossible");
else bfs();
return 0;
}
sf:暴力枚举两个草点开始烧 易错点:在于可以同地方烧
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
int n,m,ans,cao,step=1;
bool cp[15][15],fk[15][15];
int xx[] = {1,0,0,-1};
int yy[] = {0,1,-1,0};
struct node{
int x,y,z;
};
node k1,k2;
void show(){
for(int i=0;i<n;i++){
for(int j=0;j<m;j++)
cout<<fk[i][j]<<" ";cout<<endl;}
}
void show2(){
for(int i=0;i<n;i++){
for(int j=0;j<m;j++)
cout<<cp[i][j]<<" ";cout<<endl;}
}
void init(){
memset(fk,false,sizeof fk);
ans = -1 , cao = 0 ;
cin>>n>>m;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
char ch = getchar();
if(ch == '\n') ch = getchar();
if(ch == '#') cao++,fk[i][j] = true;
}
//show();
}
bool check(int x,int y){
return x>=0&&x<n&&y>=0&&y<m&&cp[x][y]&&fk[x][y];
}
void slove(int a,int b,int c,int d){
memset(cp,true,sizeof cp);
k1.x = a,k1.y = b,k1.z= 0; cp[a][b] = false;
k2.x = c,k2.y = d,k2.z= 0; cp[c][d] = false;
int cc = 2,cnt = 0;
queue<node> q;q.push(k1);q.push(k2);
while(!q.empty()){
node p = q.front();q.pop();
int x = p.x, y = p.y,z = p.z;
//cout<<x<<" "<<y<<" "<<z<<endl;
for(int i=0;i<4;i++) if(check(x+xx[i],y+yy[i])){
p.x = x+xx[i], p.y = y+yy[i] , p.z = z + 1;q.push(p);
cp[p.x][p.y] = false;cnt = p.z;cc++;
}
}
//cout<<cc<<" "<<endl;
//show2();
if(cc == cao) ans = (ans==-1)? cnt : min(cnt,ans);
}
int main()
{
int _;cin>>_;
while(_--){
init();
if(cao==1) {cout<<"Case "<<step++<<": "<<0<<endl;continue;}
for(int a=0;a<n;a++)
for(int b=0;b<m;b++)
{
if(!fk[a][b]) continue;
for(int c=a;c<n;c++)
for(int d=(c==a)?b+1:0;d<m;d++)
{
//show();
if(!fk[c][d]) continue;
//cout<<a<<" "<<b<<" "<<c<<" "<<d<<" "<<cao<<endl;
slove(a,b,c,d);
}
}
cout<<"Case "<<step++<<": "<<ans<<endl;
}
return 0;
}
//优化 就是 可以用vector存储草坐标
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
#include <cstdio>
using namespace std;
const int inf = 1e9;
int c[4]={1,0,-1,0};
int d[4]={0,1,0,-1};
int n,m;
string s;
bool vis[20][20];
bool akb[20][20];
struct node{
int x,y,num;
}e;
vector<node> v;
bool ok(int x,int y){
if(x<0||x>n||y<0||y>m) return false;
return true;
}
bool check(){
for(int i = 0;i < v.size();i ++){
e = v[i];
int x = e.x , y = e.y;
if(!vis[x][y]) return false;
}
return true;
}
int bfs(node a,node b){
memset(vis , false , sizeof vis);
queue<node> q;
int h;
a.num = 0 , b.num = 0;
q.push(a);q.push(b);
vis[a.x][a.y] = true;vis[b.x][b.y] = true;
while(!q.empty()){
e = q.front();q.pop();
int x , y ;
h = e.num;
node w;
for(int i= 0;i < 4;i++){
x = e.x + c[i] , y = e.y + d[i];
if(ok(x ,y)&&!vis[x][y]&&akb[x][y]){
w.x = x , w.y = y;
w.num = e.num + 1;
vis[x][y]= true;
q.push(w);
}
}
}
return h;
}
int main()
{
int o = 1;int _;cin>>_;
while(_--){
memset(akb , false , sizeof akb);
cin>>n>>m;
v.clear();
for(int i=0;i<n;i++){
cin>>s;
for(int j=0;j<m;j++)
if(s[j]=='#'){
akb[i][j]=true;
e.x = i , e.y = j;
v.push_back(e);
}
}
int minn = inf;
for(int i = 0;i < v.size();i ++)
for(int j = i;j < v.size();j ++){
int TnT = bfs(v[i],v[j]);
if(TnT<minn&&check()) minn = TnT;
}
cout<<"Case "<<o++<<": ";
if(minn == inf) cout<<-1<<endl;
else cout<<minn<<endl;
}
return 0;
}
sf:bfs 火要比人先进队列 易错点在于 开头不止一个火苗
这里使用了struct node 的有参构造
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string.h>
#include <queue>
using namespace std;
int n, m , u ,v;
int xx[4] = { 0, -1, 0 ,1 };
int yy[4] = { 1, 0, -1, 0 };
char sm[1005][1005];
struct node{
int x,y,step,f;
node(int xx,int yy,int sstep,int ff):x(xx),y(yy),step(sstep),f(ff) {};
};
bool bfs(){
queue<node> q;
for(int i=0;i<n;i++)
for(int j= 0;j<m;j++)
if(sm[i][j]=='F') sm[i][j] = '#' , q.push(node(i , j, 1, 0));
else if(sm[i][j]=='J') sm[i][j] = '#' , u = i , v = j;
q.push(node(u , v, 1, 1));
while(!q.empty()){
node e = q.front();q.pop();
int x , y , s , f;x = e.x , y = e.y ,s = e.step , f = e.f;
//cout<< x << " " << y <<" "<< s << " "<< f<<endl;
if(f == 1&&(x==0||y==0||x==n-1||y==m-1)) {printf("%d\n",s);return true;}
for(int i = 0;i< 4;i ++){
int a,b;
a = x + xx[i] , b = y + yy[i];
if(a<0||b<0||a>=n||b>=m||sm[a][b]=='#') continue;
//cout<< a << " " << b <<" "<< s+1 << " "<< f<<endl;
q.push(node(a,b,s+1,f));
sm[a][b]='#';
}
}
return false;
}
int main()
{
int _;scanf("%d",&_);
while(_--){
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++) scanf("%s",sm[i]);
if(!bfs()) puts("IMPOSSIBLE");
}
return 0;
}
sf:简单bfs 必有答案 需要一个前缀记录函数
#include <iostream>
#include <queue>
using namespace std;
int prex[5][5];
int prey[5][5];
int w[5][5];
int xx[] = {1,0,0,-1};
int yy[] = {0,1,-1,0};
struct node{
int x,y;
node(int xx,int yy): x(xx),y(yy) {};
};
void show(int x,int y){
if(x==-1) return ;
show(prex[x][y],prey[x][y]);
cout<<"("<<x<<", "<<y<<")"<<endl;
}
int main()
{
for(int i=0;i<5;i++) for(int j=0;j<5;j++) cin>>w[i][j];
prex[0][0] = -1 , prey[0][0] = -1;
w[0][0] = 1;
queue<node> q;q.push(node(0,0));
while(!q.empty()){
node p = q.front();q.pop();
int x = p.x, y = p.y;
for(int i=0;i<4;i++){
int u = x +xx[i],v = y+yy[i];
if(u<0||u>=5||v<0||v>=5||w[u][v]==1) continue;
w[u][v]=1;
prex[u][v] = x , prey[u][v] = y;
q.push(node(u,v));
}
}
show(4,4);
return 0;
}
sf:最小生成树思路 然后遍历 然后dfs
#include <iostream>
#include <cstring>
using namespace std;
int n,m;
bool cp[101][101];
int xx[] = {1,1,1,0,0,-1,-1,-1};
int yy[] = {1,0,-1,1,-1,1,0,-1};
bool check(int x,int y){
return x>=0&&x<n&&y>=0&&y<m&&cp[x][y];
}
void dfs(int u,int v){
for(int i=0;i<8;i++){
int a = u+xx[i] , b = v + yy[i];
if(check(a,b)){
cp[a][b] = false;
dfs(a,b);
}
}
}
void show(){
for(int i=0;i<n;i++){
for(int j=0;j<m;j++) cout<<cp[i][j]<<" ";cout<<endl;
}
}
int main()
{
while(cin>>n>>m){
if(n==0&&m==0) break;
//cout<<n<<" "<<m<<endl;
memset(cp,false,sizeof cp);
for(int i=0;i<n;i++) for(int j=0;j<m;j++){
char ch = getchar();//cout<<i<<" "<<j<<" "<<ch<<endl;
while(ch!='@'&&ch!='*') ch = getchar();
if(ch=='@') cp[i][j] = true;
}
//show();
int ans = 0;
for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(cp[i][j]){
cp[i][j] = false;ans++;dfs(i,j);
}
cout<<ans<<endl;
}
return 0;
}
sf:bfs 然后易错点在于 :必须一个容器为空,
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
int x,y,z,cnt;
bool fk[1000005];
struct node{
int u,v,w,step;
node(int uu,int vv,int ww,int ss):u(uu),v(vv),w(ww),step(ss) {};
};
int gcd(int a,int b) {return b==0?a:gcd(b,a%b);}
bool bfs(){
queue<node> q;q.push(node(x,0,0,0));fk[x*10000] = false;
while(!q.empty()){
node p = q.front();q.pop();
int u = p.u , v = p.v , w = p.w,step = p.step;
//cout<<u<<" "<<v<<" "<<w<<" "<<step<<" "<<cnt<<endl;
if(u == cnt || v == cnt || w == cnt) {
step = (!u||!v||!w)?step:step+1;
cout<<step<<endl;return true;
}
int uu,vv,ww,tnt;
if(u){
uu = u+v>=y?u+v-y:0;
vv = u+v>=y?y:u+v;
ww = w;
tnt = uu*10000+vv*100+ww;
if(fk[tnt]){fk[tnt]=false;q.push(node(uu,vv,ww,step+1));}
uu = u+w>=z?u+w-z:0;
vv = v;
ww = u+w>=z?z:u+w;
tnt = uu*10000+vv*100+ww;
if(fk[tnt]){fk[tnt]=false;q.push(node(uu,vv,ww,step+1));}
}
if(v){
uu = u+v;
vv = 0;
ww = w;
tnt = uu*10000+vv*100+ww;
if(fk[tnt]){fk[tnt]=false;q.push(node(uu,vv,ww,step+1));}
uu = u;
vv = v+w>=z?v+w-z:0;
ww = v+w>=z?z:v+w;
tnt = uu*10000+vv*100+ww;
if(fk[tnt]){fk[tnt]=false;q.push(node(uu,vv,ww,step+1));}
}
if(w){
uu = u+w;
vv = v;
ww = 0;
tnt = uu*10000+vv*100+ww;
if(fk[tnt]){fk[tnt]=false;q.push(node(uu,vv,ww,step+1));}
uu = u;
vv = v+w>=y?y:v+w;
ww = v+w>=y?v+w-y:0;
tnt = uu*10000+vv*100+ww;
if(fk[tnt]){fk[tnt]=false;q.push(node(uu,vv,ww,step+1));}
}
}
return false;
}
int main()
{
while(cin>>x>>y>>z){
if(x==0&&y==0&&z==0) break;
if(x%2) {puts("NO");continue;}
cnt = x/2;memset(fk,true,sizeof fk);
if(cnt%gcd(x,gcd(y,z))) {puts("NO");continue;}
if(!bfs()) puts("NO");
}
return 0;
}
#include <iostream>
#include <queue>
#include <cstring>
#include <string.h>
#include <cstdio>
using namespace std;
int s, n, m;
bool cp[101][100][100];
struct node{
int x,y,z,num;
node(int xx,int yy,int zz,int nn):x(xx),y(yy),z(zz),num(nn) {};
};
node e = node(0,0,0,0);
bool bfs(){
int tt = s / 2;
queue<node> q;
q.push(node(s,0,0,0));
cp[s][0][0] = true;
while(!q.empty()){
int a,b,c,x,y,z;
e = q.front();q.pop();
a = e.x , b = e.y , c = e.z;
//cout<<a<<" "<<b<<" "<<c<<endl;
if(a == tt|| b == tt || c == tt){
if(!a||!b||!c) cout<<e.num<<endl;
else cout<<e.num+1<<endl;
return true;
}
for(int i=0;i<6;i++){
if(i==0) if(b==n) continue;else x = a - min(a ,n - b) , y = b + min(a , n - b) , z = c;
else if(i==1) x = a + b , y = 0 , z = c;
else if(i==2) if(c==m) continue;else x = a - min(a ,m - c) , y = b , z = c + min(a ,m - c);
else if(i==3) x = a + c , y = b , z = 0;
else if(i==4) if(b==n) continue;else x = a , y = b + min(c ,n - b) , z = c - min(c ,n - b);
else if(i==5) if(c==m) continue;else x = a , y = b - min( b ,m - c ), z = c + min( b ,m - c );
if(cp[x][y][z]) continue;cp[x][y][z] = true;
q.push(node(x,y,z,e.num+1));
}
}
return false;
}
int main()
{
while(cin>>s>>n>>m&&s){
if(s%2) {puts("NO");continue;}
memset(cp,false,sizeof cp);
if(!bfs()) puts("NO");
}
return 0;
}
sf:bfs加上两个记录长度的状态函数(类似求最短路径)
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
const int inf = 1e9;
int n,m;
int xx[4] = {1,0,0,-1};
int yy[4] = {0,-1,1,0};
char mp[205][205];
int a[205][205];
int b[205][205];
int ans;
struct node{
int x , y , f;
node(int xx , int yy , int ff):x(xx),y(yy),f(ff) {};
};
node e = node(0,0,0);
int bfs(){
ans = inf;
memset(a,-1,sizeof a);
memset(b,-1,sizeof b);
queue<node> q;
for(int i = 0;i<n;i++)
for(int j = 0;j<m;j++)
if(mp[i][j]=='Y') q.push(node(i , j , 0)) , a[i][j] = 0;
else if(mp[i][j]=='M') q.push(node(i , j, 1)) , b[i][j] = 0;
while(!q.empty()){
int x, y , u, v;
e = q.front();q.pop();
x = e.x, y = e.y;
for(int i=0;i<4;i++){
u = x + xx[i] , v = y + yy[i];
if(u<0||v<0||u>=n||v>=m) continue;
if(mp[u][v]=='#') continue;
if(e.f==0&&a[u][v]== -1){
a[u][v] = a[x][y] + 1;
if(mp[u][v]=='@'&&b[u][v]!=-1&&(a[u][v]+b[u][v] < ans)) ans = a[u][v]+b[u][v];
q.push(node(u,v,e.f));
}
else if(e.f==1&&b[u][v]==-1){
b[u][v] = b[x][y] + 1;
if(mp[u][v]=='@'&&a[u][v]!=-1&&(a[u][v]+b[u][v] < ans)) ans = a[u][v]+b[u][v];
q.push(node(u,v,e.f));
}
}
}
return ans;
}
int main()
{
while(cin>>n>>m){
for(int i=0;i<n;i++) scanf("%s",mp[i]);
cout<<bfs()*11<<endl;
}
return 0;
}