b_lc_拆分字符串使唯一子字符串的数目最大 & 矩阵的最大非负积(回溯+剪枝)
拆分字符串使唯一子字符串的数目最大
给你一个字符串 s ,请你拆分该字符串,并返回拆分后唯一子字符串的最大数目。
字符串 s 拆分后可以得到若干 非空子字符串 ,这些子字符串连接后应当能够还原为原字符串。但是拆分出来的每个子字符串都必须是 唯一的 。
思路
简单模拟+注意边界,不加剪枝也可以过,剪枝为:当剩下的字符全部全部拆成一个字符都≤历史答案时,提前返回
class Solution {
public:
unordered_map<string, bool> m;
int ans=0;
void dfs(int l, string& s) {
if (m.size()+s.size()-l<=ans) return;
if (l>=s.size()) {
ans=max(ans, (int)m.size());
return;
}
for (int r=l; r<=s.size(); r++) {
string sub=s.substr(l, r-l+1);
if (!m[sub]) {
m[sub]=1;
dfs(r+1, s);
m.erase(m.find(sub));
}
}
}
int maxUniqueSplit(string s) {
dfs(0, s);
return ans;
}
};
矩阵的最大非负积
在从左上角 (0, 0) 开始到右下角 (rows - 1, cols - 1) 结束的所有路径中,找出具有 最大非负积 的路径。路径的积是沿路径访问的单元格中所有整数的乘积。
返回 最大非负积 对 109 + 7 取余 的结果。如果最大积为负数,则返回 -1
1 <= rows, cols <= 15
-4 <= grid[i][j] <= 4
思路
- 剪枝1:如果乘积为0,也可以返回,因为后面都是0,但159/159超时,
- 不慌,再优化一下常数:把max改为if,1640ms飘过
- 注意点:尽量避免在运算过程中取模,会导致结果不正确
typedef long long ll;
const ll mod=1e9+7, N=20, d[2][2] = { {1,0},{0,1} };
class Solution {
public:
int n,m,vis[N][N];
ll ans=-10000000;
void dfs(int x, int y, ll pro, vector<vector<int>>& g) {
if (x==n-1 && y==m-1 && pro>=0) {
if (pro>ans) ans=pro;
return;
}
if (pro==0) {
if (pro>ans) ans=pro;
return;
}
for (int k=0; k<2; k++) {
int tx=x+d[k][0], ty=y+d[k][1];
if (tx>=0 && tx<n && ty<m && ty>=0 && !vis[tx][ty]) {
vis[tx][ty]=1;
dfs(tx,ty,pro*g[tx][ty],g); //注意点
vis[tx][ty]=0;
}
}
}
int maxProductPath(vector<vector<int>>& g) {
n=g.size(), m=g[0].size();
bool allneg=1;
for (int i=0; i<n && allneg; i++)
for (int j=0; j<m; j++) if (g[i][j]>=0) {
allneg=false;
break;
}
if (allneg) return -1;
vis[0][0]=1;
dfs(0,0,g[0][0],g);
return ans<0 ? -1 :ans%mod;
}
};