假期训练八(poj-2965递归+枚举,hdu-2149,poj-2368巴什博奕)

题目一(poj-2965):传送门

思路:递归+枚举,遍历每一种情况,然后找出最小步骤的结果,与poj-1753类似。

#include<iostream>
#include<cstdio>
#include<cstring>
//#include<ctime>
using namespace std;
int x[20],y[20],xx[20],yy[20],ans=99;
char str[20];
int a[20][20];
void turn(int len)
{
    int x=len/4,y=len%4;
    for(int i=0;i<4;i++)
    {
        a[x][i]=!a[x][i];
        a[i][y]=!a[i][y];
    }
    a[x][y]=!a[x][y];
}
bool pd()
{
    for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
        if(a[i][j]!=1) return false;
    return true;
}
void dfs(int len,int num) //要用len,否则时间超限。 
{
    if(pd())
    {
        if(ans>num)
        {
            ans=num;
            for(int i=1;i<=ans;i++)
            {
                xx[i]=x[i];
                yy[i]=y[i];
            }
        }
        return ;
    }
    if(len>=16) return ; //基准情形 
    dfs(len+1,num);//先搜索 
    turn(len); //再变化 
    x[num+1]=len/4+1;
    y[num+1]=len%4+1;
    dfs(len+1,num+1); //记得回溯。 
    turn(len);
}
int main(void)
{
    int i,j;
    //int st=clock(),ed;
    for(i=0;i<4;i++)
    {
        scanf("%s",str);
        for(j=0;j<4;j++) 
        if(str[j]=='-') a[i][j]=1;
        else a[i][j]=0;
    }
    dfs(0,0);
    printf("%d\n",ans);
    for(i=1;i<=ans;i++)
    {
        printf("%d %d\n",xx[i],yy[i]);
    }
    //ed=clock();
    //printf("time==%d\n",ed-st);
    return 0;
}



//原来用x,y作为参数,时间超限 
/*#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
using namespace std;
int a[10][10],mi=99;
int x[100],y[100],cnt=0;
int xx[100],yy[100];
char str[10];
bool pd()
{
    for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
        if(a[i][j]==1) return false;
    return true;
}
void turn(int x,int y)
{
    for(int i=0;i<4;i++)
    {
        a[x][i]=!a[x][i];
        a[i][y]=!a[i][y];
    }
    a[x][y]=!a[x][y];
}
void dfs(int x1,int y1,int num)
{
    if(pd())
    {
        if(mi>num)
        {
            mi=num;
            for(int i=1;i<=num;i++)
            {
                xx[i]=x[i];
                yy[i]=y[i];
            }
        }
        return ;
    }
    if(x1*y1>9) return ;
    
    if(y1==3) dfs(x1+1,0,num);
    else dfs(x1,y1+1,num);
    turn(x1,y1);
    x[num+1]=x1+1;y[num+1]=y1+1;
    if(y1==3) dfs(x1+1,0,num+1);
    else dfs(x1,y1+1,num+1);
    turn(x1,y1);
}
int main(void)
{
    int i,j;
    int st,ed;
    st=clock();
    for(i=0;i<4;i++)
    {
        scanf("%s",str);
        for(j=0;j<4;j++)
        if(str[j]=='+') a[i][j]=1;
        else a[i][j]=0;
    }
    dfs(0,0,0);
    printf("%d\n",mi);
    for(i=1;i<=mi;i++)
    {
        printf("%d %d\n",xx[i],yy[i]);
    }
    ed=clock();
    printf("time==%d\n",ed-st);
    return 0;
}*/
View Code

 

题目二(poj-2368):传送门

思路:巴什博奕,求出使后者成功的最小的L,就是求n的非一最小因子-1,要用素数筛法,否则超时。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100100;
int a[maxn];
int main(void)
{
    int n,i,m;
    while(~scanf("%d",&n))
    {
        int len=0;
        for(i=1;i*i<=n;i++)
        {
            if(n%i==0)
            {
                a[len++]=i;
                a[len++]=n/i;
            }
        }
        sort(a,a+len);
        int fg=0;
        for(i=0;i<len;i++)
        {
            if(a[i]>=3)
            {
                fg=1;
                printf("%d\n",a[i]-1);
                break;
            }
        }
        if(fg==0) printf("0\n");
    }
    return 0;
} 
View Code

 

总结:递归不要忘记确立分清楚基准情况,先搜索,再回溯。

posted @ 2019-01-14 14:19  麟阁  阅读(140)  评论(0编辑  收藏  举报