T3.IP地址(DFS) 题面 题目链接:code.juejin.cn/pen/7180201…
思路 思路比较简单,不过数据处理起来有一点麻烦
首先这一串可以看作数字和非数字组成,对于非数字部分,我们需要替换成字符串中未出现的数字,并且重复的字母表示同一个数字,那么我们就处理这个非数字字母和数字的对应关系就好了,那么这个就可以用回溯搜索来匹配这个关系,我们每一层搜索就确定一个字母和一个数字的匹配,然后搜索的出口就是将所有出现的字母与数字匹配完成(当然也有可能不存在字母,那就直接进行检查环节)
匹配完成后就是将对应的字母替换成数字,然后取校验这个数字是否合法,比如不能存在前导 0 00 ,不能大于 255 255255 ,因为 ip 地址是一个四位的值,那么我们一一校验即可,如果满足条件,那么我们就直接输出这个结果即可
然后还有个问题就是断点,其实我们就可以想象成.在字符串中放置的方法,其实就是一个三重循环即可,.是不能放在最左边和最右边的,那么其位置的范围就是第一个字符的右边到,倒数第二个字符的右边,我这里就是将i表示的含义就是将.放在第i个字符的右边,j、k也是如此,那么这个问题到这里就结束了
代码 `#include<bits/stdc++.h> using namespace std; #define ll long long #define endl "\n"
bool vis[10]; map<char,int> mp; set st; vector vec; int vec_len; string sa[4],sb[4];
bool check(string ss) { if(ss[0] == '0' && ss.size() != 1) return false; int kk = 0; for(int i = 0;i < ss.size(); ++i) { if(ss[i] < '0' || ss[i] > '9') return false; kk = kk * 10 + (ss[i] - '0'); } if(kk > 255 || kk < 0) return false; return true; }
void dfs(int loci) { if(loci == vec_len) { for(int i = 0;i < 4; ++i) { for(int j = 0,loc_len = sa[i].size();j < loc_len; ++j) { if(sa[i][j] >= '0' && sa[i][j] <= '9') sb[i][j] = sa[i][j]; else { if(mp[sa[i][j]] < 0 || mp[sa[i][j]] > 9) return; sb[i][j] = char(mp[sa[i][j]] + '0'); } } if(check(sb[i]) == false) return; } string loc_ss = sb[0]; for(int i = 1;i < 4; ++i) { loc_ss.append("."); loc_ss.append(sb[i]); } cout<<loc_ss<<endl; return; } for(int i = 0; i <= 9; ++i) { if(vis[i]) continue; mp[vec[loci]] = i; vis[i] = true; dfs(loci + 1); vis[i] = false; mp[vec[loci]] = -1; } }
int main() { ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); string ss; cin>>ss; int len = ss.size(); if(len < 4 || len > 12) return 0;//no answer for(int i = 0;i < len; ++i) if(ss[i] >= '0' && ss[i]<= '9') vis[ss[i]-'0'] = true; else st.insert(ss[i]); for(auto it : st) vec.push_back(it); vec_len = vec.size(); for(int i = 0; i < len-1; ++i) { for(int j = i + 1;j < len-1; ++j) { for(int k = j + 1 ;k < len - 1; ++k) { sa[0] = ss.substr(0,i + 1); sa[1] = ss.substr(i + 1,j - i); sa[2] = ss.substr(j + 1,k - j); sa[3] = ss.substr(k + 1,len-k-1); for(int l = 0;l < vec_len; ++l) mp[vec[l]] = -1; for(int l = 0;l < 4; ++l) { sb[l] = sa[l]; } dfs(0); } } }
return 0;
}`
一个很简单的图的连通问题,我们只需要找到最大的连通块就行,思路很多种,最简单的就是写一个DFS,只要找到空闲的位置,我们就从这个点开始搜索,并且在搜索的过程中记录这个连通块的大小,最后更新一下ans值