4123: 马走日,2797:最短前缀 Trie,2362:Square 能否拼接为正方形

6 篇文章 0 订阅

4123: 马走日 深度优先搜索 + 回溯

///马走日
int f[21][22],n,m,t; //f数组记录点有没有走过

int x[10]={-2,-2,-1,1,2,2,1,-1},y[10]={-1,1,2,2,1,-1,-2,-2};//八个方向
int x1,y1,ans;
void dfs(int a,int b)   //搜索过程
{
    bool p=true;    //标记,判断马是否可以遍历整个棋盘
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(f[i][j]==0) //如果该点走过
            {
                p=false;   //标记为错误
                break; //结束内层循环
            }
        }
    }
    if(p==true) //如果可以遍历整个棋盘,就将方法数加1
    {
        ans++;
        return; //不用在搜下去了
    }
    for(int i=0;i<=7;i++)   //枚举马走的8个方向
    {
        int l=a+x[i];
        int k=b+y[i];
        if(f[l][k]==1)  //如果该点曾经走过,就结束当此循环
            continue;
        if(l>0&&l<=n&&k>0&&k<=m)    //判断是否越界
        {
            f[l][k]=1;   //将该点标记为1,表示不能走了
            dfs(l,k);       //将当前坐标作为新的起点,继续递归马要走的下一步
            f[l][k]=0;  //回溯
        }
    }
}

int main4123() {
    scanf("%d",&t); //输入有多少组测试数据
    for(int i=1;i<=t;i++)
    {
        scanf("%d %d %d %d",&n,&m,&x1,&y1); //输入起始坐标与终点坐标
        x1++;
        y1++;
        memset(f,0,sizeof(f));  //将f数组清空
        f[x1][y1]=1;    //起点不能再走
        ans=0;      //方案数清0
        dfs(x1,y1);//开始搜索,将起点的坐标作为第一个搜索的
        printf("%d\n",ans); //输出方案数
    }
}

2797:最短前缀 Trie

利用字典树实现,当节点的num为1时,说明为唯一的前缀 

//[openjudge] 2797最短前缀 Trie
struct Trie
{
    Trie *next[26];
    int num;
    Trie()
    {
        for (int i = 0; i < 26; i++)
            next[i] = NULL;
        num = 0;
    }
};
Trie root;
void insert(char *s){
    Trie *p = &root;
    for (int i = 0; s[i] ; ++i) {
        int tt = s[i] - 'a';
        if (p->next[tt]==NULL)
            p->next[tt] = new Trie;
        p = p->next[tt];
        p -> num++;
    }
}

void find(char *s){
    Trie *p = &root;
    for (int i = 0; s[i] ; ++i) {
        int tt = s[i] - 'a';
        if (p->next[tt]==NULL)
            return;
        p = p->next[tt];
        printf("%c",s[i]);
        if (p->num==1)
            return;
    }
}


int main2797()
{
    int n = 0;
    char word[1010][22];

    while (~scanf("%s", word[n])){
        insert(word[n]);
        n++;
    }

    for (int i = 0; i < n; ++i) {
        printf("%s ", word[i]);
        find(word[i]);
        printf("\n");
    }

    return 0;
}

2362:Square  能否拼接为正方形  DFS+回溯

// dfs时带返回值 回溯时与不带返回值的不一样,判断终止条件也不太一样
// 判断终止条件及终止条件应该有哪些变化时,只需举一个正确终止时的情况去判断

int visit[99999];int ave;
int number[99999];int n,m;
bool dfs_square(int sum , int index , int cnt){
    if (sum == ave){
        cnt ++;
        if (cnt==3)
            return true;
        sum = 0;//搜索成功某一条边时,要初始化sum和index
        index = 0;
    }

    for (int i = index; i < m; ++i) {
        if (sum + number[i]>ave)
            break;
        if (!visit[i]){
            visit[i] = 1;
            if(dfs_square(sum + number[i],i+1,cnt))
                return true;
            visit[i] = 0;//注意,搜索失败,回溯
        }
    }
    return false;
}

int square(){
    cin>>n;
    while (n--){
        cin >> m;
        int sum = 0;
        for (int i = 0;i<m;i++){
            cin>>number[i];
            sum += number[i];
        }
        if (sum%4)
            printf("no\n");
        else {
            memset(visit,0, sizeof(visit));
            sort(number,number + m);
            ave = sum / 4;
            if(dfs_square(0,0,0))
                printf("yes\n");
            else
                printf("no\n");
        }

    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值