组合数输出
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
typedef long long ll;
int n,m;
vector<int> v;
void slove(int x)
{
if(v.size()==m)///组合数满了,输出
{
int flag=0;
for(int i=0;i<m;i++) printf("%3d",v[i]);
printf("\n");
return;
}
if(x>n) return ;///超出边界,返回
for(int i=x;i<=n;i++)
{
v.push_back(i);///选择数i,然后进入下一层搜索
slove(i+1);
v.pop_back();///回溯,在递归回去的时候将这个数还原为原来未访问的状态,不选择这个数,进入循环的下一个数
}
}
int main()
{
cin>>n>>m;
slove(1);
}
问题 H: 【搜索】售货员的烦恼(trouble)
题目:
一间冰淇淋商店刚刚开张,外面有2×N个人购买1元的冰淇淋,其中一半人拿着1张2元人民币,另一半人拿一张1元人民币。售货员很粗心,没有准备零钱,要使出售过程中不发生找钱困难的问题,这2×N个人应该如何排队?请你帮售货员找出所有方案数量的总和。
输入
一个整数N(N≤15)。
输出
方案总数M。
代码+注释:
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
typedef long long ll;
int ans=0,n;
int tot1=0,tot2=0;
void slove(int index)
{
if(tot1>n||tot2>n||tot2>tot1||index>2*n) return;///不符合条件,剪枝
else if(index==2*n) {
ans++;return;}///达到终点,ans++
else
{
tot1++;///放1
slove(index+1);///向下一层搜索
tot1--,tot2++;///不放1,放2
slove(index+1);///向下一层搜索
tot2--; return;///回溯
}
}
int main()
{
cin>>n;
slove(1);
cout<<ans<<endl;
}
问题 I: 【搜索】装箱问题
题目:
有一个箱子容量为v(正整数,0≤v≤20000),同时有n个物品(0≤n≤30),每个物品有一个体积(正整数)。要求从m个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
输入
第1行两个整数v和n。
第2行n个数,表示n个物品的体积。
输出
一个整数,表示箱子剩余空间。
重要
#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
using namespace std;
int a[35];
int dp[35][20005];
int n,w;
int solve(int index,int val)///记忆化搜索
{
if(dp[index][val]) return dp[index][val];
if(index>n||val<0) return 0;///到达边界,返回0
if(val>=a[index])///dp[i][v]=max(dp[i+1][v-a[i]]+a[i],dp[i][v]),选a[i],或者不选a[i]
dp[index][val]=max(solve(index+1,val),a[index]+solve(index+1,val-a[index]));
else
dp[index][val]=solve(index+1,val);
return dp[index][val];
}
int main()
{
cin>>w>>n;
for(int i=1;i<=n;i++) cin>>a[i],dp[1][a[i]]=a[i];
solve(1,w);
cout<<w-solve(1,w)<<endl;
}
问题 b: 【搜索】素数路
题目:
已知一个四位的素数,要求每次修改其中的一位,并且要保证修改的结果还是一个素数,还不能出现前导零。你要找到一个修改数最少的方案,得到我们所需要的素数。
例如把1033变到8179,这里是一个最短的方案:
1033
1733
3733
3739
3779
8779
8179
修改了6次。
输入
1行,两个四位的素数(没有前导零),表示初始数和目标数。
输出
一个数,表示最少的操作次数。如果不可能,输出“Impossible”。
#include <iostream>
#include <queue>
#include <cstdio>
using namespace std;
int n,m;
int prime[20000];
int a[20000];
int visit[20000];
void getprime()
{
int cnt=0;a[1]=0;
for(int i=2;i<20000;i++)
{
if(a[i]==0)prime[cnt++]=i;
for(int j=0;j<cnt&&prime[j]*i<20000;j++)
{
a[i*prime[j]]=1;
if(i%prime[j]==0)break;
}
}
}
struct node
{
int ori;///原来的数
int a,b,c,d;///千,百,十,个位
int sign;///改变了哪一位,防止重复改变同一位
int step;///步数
}s,t;
queue<node>q;
int bfs(int ori,int a1,int b,int c,int d)
{
getprime();///打表
q.push({
ori,a1,b,c,d,0,0});
while(!q.empty())
{
t=q.front();q.pop();
visit[t.ori]=true;
if(t.ori==m) return t.step;
for(int i=0;i<=9;i++)
{
///获取每一位改变后的数字,记得减去的是t.a,t.b,t.c,t.d,不是a1,b,c,d
int change1=t.ori-t.a*1000+i*1000,change2