dfs中关于选数类的问题:
有两种dfs:
以后面对这类问题要常采用第二种dfs,原因是,第一种相当于选数是所有的情况都是组合,第二种都是排列,
所以第二种更加全面,特别是与方向有关时,只能用第二种。
ps:
1.剪枝真的很重要,TLE就是这样阻止你成功的脚步的
注意理解这里的剪枝:
if (distance >= ans) //这里这个剪枝之所以能用,是因为dfs都是从左边开始一条路搜完之后才搜下一条路的,所以最左边的那条路搜完之后,就已经记录下来了一个ans
return;
2.学会卡时时间常数:int fuck即可,一般数量级在“千万”左右
void dfs(int start, int depth, int s, int t)//s,t表示总的酸度,甜度
{
if (depth >= 1)//这里是为了跳过一开始main函数中运行dfs时,一开始给出参数为s=1,t=0的影响
{
ans = min(abs(s - t), ans);//一步最小的也可以
}
//start为目前所选数(配料)的编号
if(depth==n){ //这里要注意传进来以后,满足结束条件以后,要再做一次操作
return ;
}
for(int i=start;i<=n;i++){
dfs(i + 1, depth + 1, s*a[i], t+b[i]);//参数一加,或者参数一乘,就表示这次操作已经选完了
} //第一次也是在这里选完的
}
PART TWO:
void dfs(int depth, double distance, int x)
{ //x用来记录上一次到达的点的序号
fuck++; //用来卡时间常数的变量,真心fuck~
if (fuck > 30000000)
return;
/* if (depth >= 1)
{
ans = min(ans, distance);//这个ans是在所有的dfs里变化的,一步所到达的最小不要,必须到n步,所以舍去
} */
if (distance >= ans) //这里这个剪枝之所以能用,是因为dfs都是从左边开始一条路搜完之后才搜下一条路的,所以最左边的那条路搜完之后,就已经记录下来了一个ans
return;
if (depth == n) //求满n时,才求出最短距离
{
ans = min(ans, distance);
return;
}
for (int i = 1; i <= n; i++)
{ //!!!:这里i等于1和i等于start是不一样的效果!!!,手模一次~~~
if (!vis[i])
{
vis[i] = 1;//这个标注的过程和dfs搜索时时同步的~~~
dfs(depth + 1, distance + sqrt(abs((a[i] - a[x])) * abs((a[i] - a[x])) + abs((b[i] - b[x])) * abs((b[i] - b[x]))), i);
vis[i] = 0;//
}
}
}