搜索训练(dfs+bfs)持续更新
DFS
[NOIP2000 提高组] 单词接龙
题目描述
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beast
和 astonish
,如果接成一条龙则变为 beastonish
,另外相邻的两部分不能存在包含关系,例如 at
和 atide
间不能相连。
输入格式
输入的第一行为一个单独的整数 \(n\) 表示单词数,以下 \(n\) 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在。
输出格式
只需输出以此字母开头的最长的“龙”的长度。
样例 #1
样例输入 #1
5
at
touch
cheat
choose
tact
a
样例输出 #1
23
提示
样例解释:连成的“龙”为 atoucheatactactouchoose
。
\(n \le 20\)。
题解:
首先预处理出来上一个词为第i个词,当前词为第j个词的时候,后缀与前缀相同的时候为多少记为给g[i][j]。然后模拟插入过程即可。
AC代码
#include <bits/stdc++.h>
#define Howardlhhhr ios::sync_with_stdio(false);cout.tie(0);cin.tie(0);
using namespace std;
const int N = 22;
string word[N];
int g[N][N],used[N];
int n,ans;
void dfs(string dragon,int last)
{
ans = max(ans,(int)dragon.size());
used[last] ++;
for(int i = 0;i<n;i++)
{
if(g[last][i]&&used[i]<2)
{
dfs(dragon + word[i].substr(g[last][i]),i);
}
}
used[last] --;
}
int main()
{
Howardlhhhr
cin >> n;
for(int i = 0;i<n;i++) cin >> word[i];
for(int i = 0;i<n;i++)
{
for(int j = 0;j<n;j++)
{
string a = word[i],b = word[j];
for(int k = 1;k<min(a.size(),b.size());k++)
{
if(a.substr(a.size()-k,k) == b.substr(0,k))
{
g[i][j] = k;
break;
}
}
}
}
char start;
cin >> start;
for(int i = 0;i<n;i++)
{
if(word[i][0] == start)
{
dfs(word[i],i);
}
}
cout << ans << endl;
return 0;
}
[USACO05DEC] Scales S
题目描述
约翰有一架用来称牛的体重的天平。与之配套的是 $ N \ ( 1 \leq N \leq 1000 ) $ 个已知质量的砝码(所有砝码质量的数值都在 \(32\) 位带符号整数范围内)。
每次称牛时,他都把某头奶牛安置在天平的某一边,然后往天平另一边加砝码,直到天平平衡,于是此时砝码的总质量就是牛的质量(约翰不能把砝码放到奶牛的那边,因为奶牛不喜欢称体重,每当约翰把砝码放到她的蹄子底下,她就会尝试把砝码踢到约翰脸上)。
天平能承受的物体的质量不是无限的,当天平某一边物体的质量大于 $ C \ ( 1 \leq C \leq 2^{30} ) $ 时,天平就会被损坏。砝码按照它们质量的大小被排成一行。并且,这一行中从第 \(3\) 个砝码开始,每个砝码的质量至少等于前面两个砝码(也就是质量比它小的砝码中质量最大的两个)的质量的和。
约翰想知道,用他所拥有的这些砝码以及这架天平,能称出的质量最大是多少。由于天平的最大承重能力为 \(C\),他不能把所有砝码都放到天平上。
现在约翰告诉你每个砝码的质量,以及天平能承受的最大质量,你的任务是选出一些砝码,使它们的质量和在不压坏天平的前提下是所有组合中最大的。
输入格式
第 \(1\) 行输入两个用空格隔开的正整数 $ N $ 和 $ C $。
第 \(2\) 到 $ N+1 $ 行:每一行仅包含一个正整数,即某个砝码的质量。保证这些砝码的质量是一个不下降序列。
输出格式
输出一个正整数,表示用所给的砝码能称出的不压坏天平的最大质量。
样例 #1
样例输入 #1
3 15
1
10
20
样例输出 #1
11
题解:
可行性剪枝:如果当前选的砝码已经大于最大可选的量的话,那么这条路无论怎么选,都是一个不合法的方案,故剪枝。
搜索顺序:从大到小依次搜索,因为这样能够让决策可选择性越来越少,可以先搜出答案以排除后面的答案
AC代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
typedef long long LL;
LL a[N],sum[N];
LL n,c;
LL ans;
void dfs(int k,LL now)
{
if(now > c) return;
if(now + sum[k-1]<=c)
{
ans = max(ans,now+sum[k-1]);
return;
}
ans = max(ans,now);
for(int i = k-1;i;i--)
{
if(a[i] < c )dfs(i,now+a[i]);
}
}
int main()
{
scanf("%lld%lld",&n,&c);
for(int i = 1;i<=n;i++) scanf("%lld",&a[i]),sum[i] = sum[i-1] + a[i];
dfs(n+1,0);
printf("%lld\n",ans);
return 0;
}
[NOI1999] 生日蛋糕
题目描述
7 月 17 日是 Mr.W 的生日,ACM-THU 为此要制作一个体积为 \(N\pi\) 的 \(M\) 层生日蛋糕,每层都是一个圆柱体。
设从下往上数第 \(i\)(\(1 \leq i \leq M\))层蛋糕是半径为 \(R_i\),高度为 \(H_i\) 的圆柱。当 \(i \lt M\) 时,要求 \(R_i \gt R_{i+1}\) 且 \(H_i \gt H_{i+1}\)。
由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积 \(Q\) 最小。
请编程对给出的 \(N\) 和 \(M\),找出蛋糕的制作方案(适当的 \(R_i\) 和 \(H_i\) 的值),使 \(S=\dfrac{Q}{\pi}\) 最小。
(除 \(Q\) 外,以上所有数据皆为正整数)
输入格式
第一行为一个整数 \(N\)(\(N \leq 2 \times 10^4\)),表示待制作的蛋糕的体积为 \(N\pi\)。
第二行为 \(M\)(\(M \leq 15\)),表示蛋糕的层数为 \(M\)。
输出格式
输出一个整数 \(S\),若无解,输出 \(-1\)。
样例 #1
样例输入 #1
100
2
样例输出 #1
68
题解
可行性剪枝:如果当前可以选的最大的体积比当前必须选的最小的体积要小,那么不可行,故剪枝
最优性剪枝:如果当前已经选的体积,加上估计最小值(后文会推导)要大于当前答案,后面怎么选都不可能是最优,故剪枝
搜索顺序:从大到小放体积
估计最小值推导
假设上面一层是1,最下面一层是是m
即
故有 此时的面积加上预测面积如果大于当前答案则return
对r和h的限制
首先每一层的r和h的最小值应该等于这一层的层数,(第一层最少且最少是一,故第二层最少是2依次类推),而r取最大,h和剩余体积取最小,h取最大同理。故可以得到下面不等式
AC代码
#include <bits/stdc++.h>
using namespace std;
const int M = 30,INF = 0x3f3f3f3f;
int minv[M],mins[M];
int R[M],H[M];
int n,m;
int ans = INF;
void dfs(int u,int v,int s)
{
if(v + minv[u] > n) return;
if(s + mins[u] >= ans) return;
if(s + 2 * (n-v) / R[u+1] >= ans) return;
if(!u)
{
if(v==n) ans = s;
return;
}
for(int r = min(R[u+1]-1,(int)sqrt(n-v));r>=u;r--)
{
for(int h = min(H[u+1]-1,(n-v)/r/r);h>=u;h--)
{
int t = 0;
if(u==m) t = r * r;
R[u] = r,H[u] = h;
dfs(u-1,v+r*r*h,s+2*r*h+t);
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i<=m;i++)
{
minv[i] = minv[i-1] + i * i * i;
mins[i] = mins[i-1] + 2 * i * i;
}
R[m+1] = H[m+1] = INF;
dfs(m,0,0);
printf("%d\n",ans==INF?-1:ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具