搜索
组合,n里选r个 (dfs&回溯)
#include<cstdio> using namespace std; int n,a[25],vis[25],r; void search(int x,int cnt){ if(cnt > r){ for(int i=1;i<=r;++i)printf("%d ",a[i]); putchar('\n'); return ; } for(int i=x;i<=n;++i){ if(!vis[i]){ a[cnt] = i; vis[i] = 1; search(i+1,cnt+1); vis[i] = 0; } } } void dfs(int x,int y){ if(y > r){ for(int i=1;i<=r;++i)printf("%d ",a[i]); putchar('\n'); return ; } for(int i=x;i<=n;++i){ a[y] = i; dfs(i+1,y+1); } } int main(){ scanf("%d%d",&n,&r); dfs(1,1); }
数的拆分,一个数可以被分成多少个小于自己的数的和(dfs + 回溯)
#include<cstdio> using namespace std; int n,a[25]; void dfs(int x,int y,int z){ if(y > n)return ; if(y == n){ for(int i=1;i<z;++i){ if(i > 1)putchar('+'); printf("%d",a[i]); } putchar('\n'); return ; } for(int i=x;i<n;++i){ a[z] = i; dfs(i,y+i,z+1); } } void search(int sum,int x,int y){ for(int i=x;i<n;++i){ if(i<=sum){ sum-=i; a[y] = i; if(sum == 0){ for(int i=1;i<=y;++i)printf("%d ",a[i]); putchar('\n'); } else search(sum,i,y+1); sum += i; } } } int main(){ scanf("%d",&n); search(n,1,1); }
拔河比赛
n个人,要求分成两队人,人数差不超过1,求体重差最小值
这题乍一看很吓人,其实也就是n个人中选n/2个,不断记录体重差的最小值
纯dfs
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int t,n,w[25],tot,mini; void dfs(int cur,int sum,int cnt){ if(cur == n/2){ mini = min(mini,abs(tot-sum*2)); return ; } if(cnt > n)return ; dfs(cur,sum,cnt+1); dfs(cur+1,sum+w[cnt],cnt+1); } int main(){ scanf("%d",&t); while(t--){ mini = 10000000; tot = 0; scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%d",&w[i]); tot += w[i]; } dfs(0,0,1); printf("%d\n",mini); } }