目录
例题
解题代码
缺陷
时间复杂度过高,即使剪枝优化后也只能得40%-50%左右的分数。
代码
#include<iostream>
using namespace std;
int wine = 2;
int ans = 0;
void DFS(int nowWine, int now, int nowlevel, int& nums,int& N,int&M,int n,int m);
int main() {
int N = 0, M = 0;//N为店数 M为花数
cin >> N >> M;
int nums = N + M;
DFS(2,1,1,nums,N,M,1,0);
DFS(2,0,1,nums,N,M,0,1);
cout << ans % 1000000007;
return 0;
}
//合法的情况:本次的nowlevel等于nums并且此时nowWine正好等于0
//设计:1 为遇店 0 为遇花
void DFS(int nowWine, int now, int nowlevel, int& nums, int& N, int& M, int n, int m) {
//这里出错了:不合法的情况讨论不完全:当遇店数或遇花数超出上限时,此时也不合法。
if (nowWine==0 && now==0) {
return ;
}
if (m>M || n>N) {
return;
}
//当前序列到达最后层次
if (nowlevel==nums) {
/*if (nowWine == 0&&now==1) {
ans++;
return;
}*/
if (nowWine ==1&&now==0) {
ans++;
return;
}
else {
return;
}
}
if (now==1) {
nowWine *= 2;
}
if (now == 0) {
nowWine -= 1;
}
//程序进到这里进行更深层次的DFS
DFS(nowWine,1,nowlevel+1,nums,N,M,n+1,m);
DFS(nowWine,0,nowlevel+1,nums,N,M,n,m+1);
}
代码核心骨架
递归+回溯+剪枝优化
剪枝优化
剪枝优化的作用:
将DFS递归过程中,不合法的情况剪掉,只留下合法的情况,同时节约了时间。
剪枝代码:
if (nowWine==0 && now==0) {
return ;
}
if (m>M || n>N) {
return;
}
//当前序列到达最后层次
if (nowlevel==nums) {
/*if (nowWine == 0&&now==1) {
ans++;
return;
}*/
if (nowWine ==1&&now==0) {
ans++;
return;
}
else {
return;
}
}
剪枝优化易错点
在剪枝时,一定要理解透题意,将所有的“枝”全部剪掉,即找出来全部不符合题意的情况,剪掉。
DFS函数参数设计
int nowWine:当前李白所剩的酒数
int now:当前李白遇的是店还是花
int nowlevel:当前所处排列的具体元素位置
int& nums:每一种排列所拥有的元素个数
int& N:遇到的总店数
int& M:遇到的总花数
int n:截止到当前为止,所遇到的总店数
int m:截止到当前为止,所遇到的总花数