温故而知新

vj地址:here

POJ1321

简单dfs

对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案数C

第i行放或者不放棋子,并记录第j列是否放过棋子,如果最后棋子数正好为k则为可行方案

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,k;
char map[10][10];
bool vis[10];
int cnt;
void dfs(int i,int num)
{
    if(num==k)
    {
        cnt++;
        return;
    }
    if(i>=n)return;
    //i
    int j;
    for(j=0;j<n;j++)
    {
        if(!vis[j]&&map[i][j]=='#')
        {
            vis[j]=true;
            dfs(i+1,num+1);
            vis[j]=false;
        }
    }

    //i+1
    dfs(i+1,num);
}
int main()
{
    while(~scanf("%d%d",&n,&k))
    {
        if(n==-1&&k==-1)break;
        int i;
        for(i=0;i<n;i++)scanf("%s",map[i]);
        cnt=0;
        memset(vis,false,sizeof(vis));
        dfs(0,0);
        printf("%d\n",cnt);

    }
    return 0;
}
View Code

 

POJ3297 

奶牛翻棋盘,每次会翻上下左右中五个位置

用二进制枚举第一行的状态,后面每行的状态就确定了,也就是根据上一行的状态确定要不要pushon,

然后检查最后一行是不是全为0,如果是就找到的方案

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
int mp[20][20],p[20][20],ans[20][20];
void pushon(int x,int y)
{
    p[x][y]^=1;
    p[x-1][y]^=1;
    p[x+1][y]^=1;
    p[x][y-1]^=1;
    p[x][y+1]^=1;
}
bool check(int x)
{
    memset(ans,0,sizeof(ans));
    memcpy(p,mp,sizeof(mp));
    for(int i=1;i<=m;i++)
    {
        if(x&(1<<(i-1)))
        {
            ans[1][i]=1;
            pushon(1,i);
        }
    }
    for(int i=2;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(p[i-1][j])
            {
                ans[i][j]=1;
                pushon(i,j);
            }
        }
    }
    for(int i=1;i<=m;i++)
    {
        if(p[n][i])return false;
    }
    return true;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
                scanf("%d",&mp[i][j]);
        }
        int tt=(1<<m);
        int flag=1;
        for(int i=0;i<tt;i++)//用二进制枚举第一行所有翻转的可能
        {
            if(check(i))
            {
                flag=0;
                break;
            }
        }
        if(flag)
        {
            puts("IMPOSSIBLE");
            continue;
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<m;j++)printf("%d ",ans[i][j]);
            printf("%d\n",ans[i][m]);
        }
    }
    return 0;
}
View Code

 

POJ 1426

找到一个数的任意一个倍数,要求只包含0和1

倍数可能比较大,利用同余模定理,用string来记录数字

dfs解法

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
int flag;
string ans[210];
void dfs(string str,int s,int n,int level)
{
    if(flag||level>=100){
        return;
    }
    if(s==0){
        flag=1;
        ans[n]=str;
        return ;
    }
    dfs(str+'1',(s*10+1)%n,n,level+1);
    dfs(str+'0',(s*10+0)%n,n,level+1);
}
int main()
{
    for(int i=1;i<=200;i++)
    {
        flag=0;
        dfs("1",1,i,1);
    }
    int n;
    while(~scanf("%d",&n)&&n!=0)
    {
        printf("%s\n",ans[n].c_str());
    }
    return 0;
}
View Code

bfs+剪枝 访问过的余数就不要访问了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define LL long long
struct ss
{
    int s;
    string str;
}t;
queue<ss>q;
string s[220];
bool vis[220];
void bfs(int n)
{
    memset(vis,false,sizeof(vis));
    ss a;
    a.s=1;
    a.str="1";
    while(!q.empty())q.pop();
    q.push(a);
    while(!q.empty())
    {

        a=t=q.front();
        q.pop();

        if(t.s%n==0)
        {
            s[n]=t.str;
            return ;
        }

        a.s=(a.s*10+1)%n;
        if(!vis[a.s]){
            a.str+='1';
            q.push(a);
            vis[a.s]=true;
        }

        t.s=(t.s*10+0)%n;
        if(!vis[t.s]){
            t.str+='0';
            q.push(t);
            vis[t.s]=true;
        }
    }
}
int main()
{
    for(int i=1;i<=200;i++){
        bfs(i);
    }
    int n;
    while(~scanf("%d",&n)&&n!=0)
    {
        printf("%s\n",s[n].c_str());
    }
    return 0;
}
View Code

 

POJ3126

一个四位数素数,要求改变一个数字,并且改变后仍为素数,问得到目标数字要变几次

传统广搜+剪枝,同样是剪掉访问过的前置节点

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define LL long long
#define maxn 10000
struct ss
{
    int num;
    int step;
};
bool vis[maxn];
queue<ss>q;
bool pri[maxn];
void bfs(int a,int b)
{
    memset(vis,false,sizeof(vis));
    while(!q.empty())q.pop();
    ss t,o;
    t.num=a;
    t.step=0;
    vis[t.num]=true;
    q.push(t);
    while(!q.empty())
    {
        t=q.front();
        q.pop();
       // printf("%d %d\n",t.num,t.step);
        if(t.num==b)
        {
            printf("%d\n",t.step);
            return;
        }

        for(int i=1;i<=9;i++)
        {
            int p=i*1000+t.num%1000;
            if(!vis[p]&&!pri[p])
            {
                vis[p]=true;
                o.num=p;
                o.step=t.step+1;
                q.push(o);
            }
        }
        for(int i=0;i<=9;i++)
        {
            int p=t.num/1000*1000+i*100+t.num%100;
            if(!vis[p]&&!pri[p])
            {
                vis[p]=true;
                o.num=p;
                o.step=t.step+1;
                q.push(o);
            }
        }
        for(int i=0;i<=9;i++)
        {
            int p=t.num/100*100+i*10+t.num%10;
            if(!vis[p]&&!pri[p])
            {
                vis[p]=true;
                o.num=p;
                o.step=t.step+1;
                q.push(o);
            }
        }
        for(int i=0;i<=9;i++)
        {
            int p=t.num/10*10+i;
            if(!vis[p]&&!pri[p])
            {
                vis[p]=true;
                o.num=p;
                o.step=t.step+1;
                q.push(o);
            }
        }
    }

}
void inti()
{
    memset(pri,false,sizeof(pri));
    pri[0]=pri[1]=1;
    for(int i=2;i<maxn;i++)
    {
        for(int j=i+i;j<maxn;j+=i)
        {
            pri[j]=1;
        }
    }
}
int main()
{
    inti();
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        if(a==b)
        {
            puts("0");
            continue;
        }
        bfs(a,b);
    }
    return 0;
}
View Code

 

POJ3087 

两副牌,交叉洗牌后得到新的系列,问几次能得到目标序列

简单dfs,由目标序列向前递归求解。指针引用和原指针指向的是同一个字符串,指针引用值改变会改变原指针对应的值,传入前先复制字符串

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define LL long long
#define maxn 1100
char a1[maxn],a2[maxn];
char a3[maxn*2];
int n;
int flag;
bool isEqual(char *a,char *b,int len)
{
    for(int i=0;i<len;i++)
    {
        if(a[i]!=b[i])
            return false;
    }
    return true;
}
void dfs(char *s3,int level)
{
    if(flag)return ;
    char s1[maxn],s2[maxn];
    for(int i=0;i<n;i++)
    {
        if(i%2)s1[i/2]=s3[i];
        else s2[i/2]=s3[i];
    }
    s1[n/2]=s2[n/2]='\0';



    if(isEqual(s1,a1,n/2)&&isEqual(s2,a2,n/2))
    {
        flag=level;
        return ;
    }

    for(int i=0;i<n/2;i++)
    {
        s3[i]=s1[i];
    }
    for(int i=n/2;i<n;i++)
    {
        s3[i]=s2[i-n/2];
    }

   //  printf("%s %s %s\n",s1,s2,s3);
    if(isEqual(s3,a3,n))
    {
        flag=-1;
        return ;
    }
    dfs(s3,level+1);
}
int main()
{
    int T;
    scanf("%d",&T);
    for(int i=1;i<=T;i++)
    {
        scanf("%d%s%s%s",&n,a1,a2,a3);
        n*=2;
        flag=0;
        char a33[maxn];
        strcpy(a33,a3);
        dfs(a33,1);
        printf("%d %d\n",i,flag);
    }
    return 0;
}
View Code

 

FZU2150 

做过,传送门:here

 

UVA 11624

帮助joe逃离火灾,走到边界就算逃离。joe只要一个,火没说有几处。

bfs每一步要先把人走完,再把火势走完,分别标记,如果人走之前有火的标记,则说明人来不及走,那么这条路就不能走

另外注意剪枝要细,原先我在火势走的时候是判断mp[t.x][t.y]!='#' 结果超时了,改成mp[t.x][t.y]=='.' || mp[t.x][t.y]=='J'就好了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define LL long long
char mp[1010][1010];
int r,c;
// l u r d
int dx[4]={-1,0,1,0};
int dy[4]={0,-1,0,1};
struct Point
{
    int x,y,step;
    Point(int _x,int _y,int _step):x(_x),y(_y),step(_step){}
};
int flag;
void bfs()
{
    queue<Point>joe,fire;
    while(!joe.empty())joe.pop();
    while(!fire.empty())fire.pop();
    for(int i=0;i<r;i++)
    {
        for(int j=0;j<c;j++)
        {
            if(mp[i][j]=='J')
                joe.push(Point(i,j,0));
            if(mp[i][j]=='F')
                fire.push(Point(i,j,0));
        }
    }
    int step=0;
    while(!joe.empty())
    {
        //人先走 将该步step的下一步全部更新完
        while(!joe.empty() && joe.front().step==step){
            Point t=joe.front();
            joe.pop();
        //    printf("joe: %d %d %d %c\n",t.x,t.y,t.step,mp[t.x][t.y]);
            if(mp[t.x][t.y]!='F')//没被火烧到才能走
            {
                if(t.x==r-1 || t.x==0 || t.y==c-1 || t.y==0)//走到边界
                {
                    flag=t.step+1;
                    return;
                }
                for(int i=0;i<4;i++)
                {
                    int x=t.x+dx[i];
                    int y=t.y+dy[i];
                    if(x>=0 && x<r && y>=0 && y<c && mp[x][y]=='.')
                    {
                        mp[x][y]='J';
                        joe.push(Point(x,y,t.step+1));
                    }
                }
            }
        }

        //火蔓延 更新完该步
        while(!fire.empty() && fire.front().step==step){
            Point t=fire.front();
            fire.pop();
         //    printf("fire: %d %d %d %c\n",t.x,t.y,t.step,mp[t.x][t.y]);
            for(int i=0;i<4;i++)
            {
                int x=t.x+dx[i];
                int y=t.y+dy[i];
                if(x>=0 && x<r && y>=0 && y<c && (mp[x][y]=='.'||mp[x][y]=='J'))
                {
                    mp[x][y]='F';
                    fire.push(Point(x,y,t.step+1));
                }
            }
        }

        step++;
    }

}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&r,&c);
        for(int i=0;i<r;i++){
            scanf("%s",mp[i]);
        }
        flag=0;
        bfs();
        if(flag)printf("%d\n",flag);
        else puts("IMPOSSIBLE");
    }
    return 0;
}

/*
2

4 5
#####
#J..#
#..F#
#...#

4 4
####
#J.#
#.F#
#..#
*/
View Code

 

POJ3414

两个杯子倒水,6种情况,要求最后杯中水量都为C

简单bfs ,6种情况都考虑到即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define LL long long
#define FA "\nFILL(1)"
#define FB "\nFILL(2)"
#define DA "\nDROP(1)"
#define DB "\nDROP(2)"
#define PAB "\nPOUR(1,2)"
#define PBA "\nPOUR(2,1)"
bool mp[110][110];
struct node
{
    int step;
    int va,vb;
    string path;
};
int flag;
queue<node>q;
void bfs(int VA,int VB,int C)
{
    memset(mp,false,sizeof(mp));
    node p;
    p.va=0;
    p.vb=0;
    p.step=0;
    p.path="";
    while(!q.empty())q.pop();
    q.push(p);
    while(!q.empty())
    {
        p=q.front();
        q.pop();
        if(p.va==C || p.vb==C)
        {
            flag=p.step;

            printf("%d%s",flag,p.path.c_str());
            return;
        }

        node t;
        //FILLA
        t.va=VA;
        t.vb=p.vb;
        if(!mp[t.va][t.vb])
        {
            mp[t.va][t.vb]=true;
            t.step=p.step+1;
            t.path=p.path+FA;
            q.push(t);
        }

        //FILLB
        t.va=p.va;
        t.vb=VB;
        if(!mp[t.va][t.vb])
        {
            mp[t.va][t.vb]=true;
            t.step=p.step+1;
            t.path=p.path+FB;
            q.push(t);
        }

        //DROPA
        t.va=0;
        t.vb=p.vb;
        if(!mp[t.va][t.vb])
        {
            mp[t.va][t.vb]=true;
            t.step=p.step+1;
            t.path=p.path+DA;
            q.push(t);
        }

        //DROPB
        t.va=p.va;
        t.vb=0;
        if(!mp[t.va][t.vb])
        {
            mp[t.va][t.vb]=true;
            t.step=p.step+1;
            t.path=p.path+DB;
            q.push(t);
        }

        //POURAB
        t.va=max(0,p.va-(VB-p.vb));
        t.vb=p.va-t.va+p.vb;
        if(!mp[t.va][t.vb])
        {
            mp[t.va][t.vb]=true;
            t.step=p.step+1;
            t.path=p.path+PAB;
            q.push(t);
        }

        //POURBA
        t.vb=max(0,p.vb-(VA-p.va));
        t.va=p.vb-t.vb+p.va;
        if(!mp[t.va][t.vb])
        {
            mp[t.va][t.vb]=true;
            t.step=p.step+1;
            t.path=p.path+PBA;
            q.push(t);
        }


    }
}
int main()
{
    int a,b,c;
    while(~scanf("%d%d%d",&a,&b,&c))
    {
        flag=0;
        bfs(a,b,c);
        if(!flag)puts("impossible");
    }
    return 0;
}
View Code

 

HDU1495

一瓶可乐,两个杯子,要求最后两杯中可乐一样且正好都是半瓶的量。

简单bfs,考虑6种情况即可,一定要等分地分成两杯

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
bool mp[110][110];
int N,M,S;
struct node{
    int vn,vm,vs,step;
};
queue<node>q;
void bfs()
{
    memset(mp,false,sizeof(mp));
    node a;
    a.vn=a.vm=a.step=0;
    a.vs=S;
    while(!q.empty())q.pop();
    q.push(a);
    mp[a.vn][a.vm]=true;
    while(!q.empty())
    {
        a=q.front();
        q.pop();
     //   printf("s=%d n=%d m=%d step=%d\n",a.vs,a.vn,a.vm,a.step);
        if(a.vs==max(a.vm,a.vn) && a.vs==S/2)
        {
            printf("%d\n",a.step);
            return;
        }
        //n->m
        node t;
        t.vn=max(0,a.vn-(M-a.vm));
        t.vm=a.vn-t.vn+a.vm;
        t.vs=a.vs;
        if(!mp[t.vn][t.vm])
        {
            mp[t.vn][t.vm]=true;
            t.step=a.step+1;
            q.push(t);
        }
        //m->n
        t.vm=max(0,a.vm-(N-a.vn));
        t.vn=a.vm-t.vm+a.vn;
        t.vs=a.vs;
        if(!mp[t.vn][t.vm])
        {
            mp[t.vn][t.vm]=true;
            t.step=a.step+1;
            q.push(t);
        }
        //n->s
        t.vn=max(0,a.vn-(S-a.vs));
        t.vs=a.vn-t.vn+a.vs;
        t.vm=a.vm;
        if(!mp[t.vn][t.vm])
        {
            mp[t.vn][t.vm]=true;
            t.step=a.step+1;
            q.push(t);
        }
        //s->n
        t.vs=max(0,a.vs-(N-a.vn));
        t.vn=a.vs-t.vs+a.vn;
        t.vm=a.vm;
        if(!mp[t.vn][t.vm])
        {
            mp[t.vn][t.vm]=true;
            t.step=a.step+1;
            q.push(t);
        }
        //m->s
        t.vm=max(0,a.vm-(S-a.vs));
        t.vs=a.vm-t.vm+a.vs;
        t.vn=a.vn;
        if(!mp[t.vn][t.vm])
        {
            mp[t.vn][t.vm]=true;
            t.step=a.step+1;
            q.push(t);
        }
        //s->m
        t.vs=max(0,a.vs-(M-a.vm));
        t.vm=a.vs-t.vs+a.vm;
        t.vn=a.vn;
        if(!mp[t.vn][t.vm])
        {
            mp[t.vn][t.vm]=true;
            t.step=a.step+1;
            q.push(t);
        }

    }
    puts("NO");
}
int main()
{
    while(~scanf("%d%d%d",&S,&N,&M))
    {
        if(S==0&&N==0&&M==0)break;
        if(S%2)
        {
            puts("NO");
            continue;
        }
        bfs();
    }
    return 0;
}
View Code

 

HDU2612

两人去一家KFC,要求选择两人总路程最短的其中一家KFC。

 简单题bfs 只要以两个人为起点各自进行bfs求出到各个餐厅的最短距离,然后暴力出最小值即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
int n,m;
char mp[220][220];
int yy[220][220];
int mm[220][220];
int dx[4]={-1,0,1,0};
int dy[4]={0,-1,0,1};
bool vis[220][220];
struct node
{
    int x,y,step;
    node(int _x,int _y,int _step):x(_x),y(_y),step(_step){}
};
queue<node>q;
void bfs()
{
    memset(vis,false,sizeof(vis));
    while(!q.empty())q.pop();
    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));
           }
       }
    }
    vis[q.front().x][q.front().y]=true;
    while(!q.empty())
    {
        node t=q.front();
        q.pop();
        yy[t.x][t.y]=t.step;
        for(int i=0;i<4;i++)
        {
            int x=t.x+dx[i];
            int y=t.y+dy[i];
            if(x>=0 && x<n && y>=0 && y<m && mp[x][y]!='#' && !vis[x][y] )
            {
                vis[x][y]=true;
                q.push(node(x,y,t.step+1));
            }
        }
    }

    memset(vis,false,sizeof(vis));
    while(!q.empty())q.pop();
    for(int i=0;i<n;i++)
    {
       for(int j=0;j<m;j++)
       {
           if(mp[i][j]=='M')
           {
               q.push(node(i,j,0));
           }
       }
    }
    vis[q.front().x][q.front().y]=true;
    while(!q.empty())
    {
        node t=q.front();
        q.pop();
        mm[t.x][t.y]=t.step;
        for(int i=0;i<4;i++)
        {
            int x=t.x+dx[i];
            int y=t.y+dy[i];
            if(x>=0 && x<n && y>=0 && y<m && mp[x][y]!='#' && !vis[x][y] )
            {
                vis[x][y]=true;
                q.push(node(x,y,t.step+1));
            }
        }
    }
    int ma=100000000;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            if(mp[i][j]=='@')
            {
                if(yy[i][j]+mm[i][j]<ma)
                {
                    ma=yy[i][j]+mm[i][j];
                }
            }
        }
    }
    printf("%d\n",ma*11);
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=0;i<n;i++)
            scanf("%s",mp[i]);
        bfs();
    }
    return 0;
}
View Code

 

posted on 2015-07-19 11:34  kylehz  阅读(130)  评论(0)    收藏  举报