UVA 1262 - Password

下午写的这个题。 用回溯写的。  各种WA。 总是找不出 BUG。 


晚上喝 峰哥 楷神 出去吃了个烧烤。 回来一想就找出 BUG 然后A了。 爽歪歪。


这个题 我思路是比较习惯横向的 所以我先把纵向判断 反向 调换之后 改成横向。


写回溯  肯定不会超时。 数据太小。  就直接爆了。  但是交上去是WA了。 就感觉 不会改了。 找了好几遍BUG 没找到。


最后终于想到了。  我没有出样例。 只是想到了 某一个特殊情况 而改出来的。


举例吧

A A A A A

B B B B B

C C C C C

D D D D D

E E E E E

F F F F F


A A A A A

A B B B B

C C C C C

D D D D D

E E E E E

F F F F F 

唯一不同就是  第二行 把B变成了A  那么在后面 就可能某第  k个  与 第1 个相同。 注意在 筛选的时候 如果有相同的元素 去重就可以了


上代码。  我用 set 实现的去重。   用vector 保存的  字符 (比数组方便的多)  string 保存路径



#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <cctype>
using namespace std;
#define ll long long
typedef unsigned long long ull;
#define maxn 1000+10
#define INF 1<<30
int n;
int sum = 0;
char s1[100][100],s2[100][100];
vector <char> ss1[maxn];
vector <char> ss2[maxn];
int dfs(int h,int num,string s){
    if(num == 5){
        sum ++;
        if(sum == n){
            cout << s <<endl;
            return 1;
        }
        return 0;
    }
    else {
        for(int j = 0; j < ss1[h].size(); j++){
            for(int k = 0; k < ss2[h].size(); k++){
                if(ss1[h][j] == ss2[h][k]){
                    if(dfs(h+1,num+1,s + ss1[h][j]))
                        return 1;
                }
            }
        }
    }
    return 0;
}
int main (){
    int counts;
    scanf("%d",&counts);
    while(counts--){
        scanf("%d",&n);
        sum = 0;
        memset(s1,0,sizeof(s1));
        memset(s2,0,sizeof(s2));
        for(int i = 0; i < 6; i++)
            scanf("%s",s1[i]);
        for(int i = 0; i < 5; i++)
            ss1[i].clear();
        set <char> q1[maxn];
        for(int i = 0; i < 5; i++){
            for(int j = 0; j < 6; j++){
                if(!q1[i].count(s1[j][i])){
                    ss1[i].push_back(s1[j][i]);
                    q1[i].insert(s1[j][i]);
                }
            }
            sort(ss1[i].begin(),ss1[i].end());
        }
        set <char> q2[maxn];
        for(int i = 0; i < 6; i++)
            scanf("%s",s2[i]);
        for(int i = 0; i < 5; i++)
            ss2[i].clear();
        for(int i = 0; i < 5; i++){
            for(int j = 0; j < 6; j++){
                if(!q2[i].count(s2[j][i])){
                    ss2[i].push_back(s2[j][i]);
                    q2[i].insert(s2[j][i]);
                }
            }
            sort(ss2[i].begin(),ss2[i].end());
        }
        int flag = 0;
        for(int j = 0; j < ss1[0].size(); j++){
            for(int k = 0; k < ss2[0].size(); k++){
                if(ss1[0][j] == ss2[0][k]){
                    string s;
                    if(dfs(1,1,s + ss1[0][j])){
                        flag = 1;
                        break;
                    }
                }
            }
            if(flag)
                break;
        }
        if(!flag)
            printf("NO\n");
    }
    return 0;
}


然后回溯就很简单了。 




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值