dfs+search

1.数的划分

点击查看搜索
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std; 
int n,m,a[100];
void dfs(int x,int y,int z)//shu  zong  wei
{
	if(y>n)return;
	if(y==n)
	{
		for(int i=1;i<z;i++)//不取等 
		{
			printf("%d ",a[i]);
		}
		printf("\n");
		return;
	}
	for(int i=x;i<n;i++)
	{
		a[z]=i;
		dfs(i,y+i,z+1);
	}
}
int main()
{
	scanf("%d",&n);
	dfs(1,0,1);
	return 0;
}
点击查看递推
/*把n看成是n个小球,k看成是k个盒子

  那么题目就变成了把n小球放到k个盒子,且每个盒子都至少有1个小球的问题。

  那么把n个小球放到k个盒子里的情况总数 = 1.至少有1个盒子放1个小球的情况总数 + 2.每个盒子都有多于1个小球的情况总数

  那么这里 1 相当于 把n-1个小球放到k-1个盒子里的情况总数

  2 相当于 把n-k个小球放到k个盒子里的情况总数

  到了这里就可以发现是递推咯。

  公式为 f(n,k) = f(n-1,k-1) + f(n-k,k)
*/
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int n, k, f[205][10];
int main() {
    scanf("%d%d", &n, &k);//不太一样,划分成k个数
    for (int i = 1; i <= n; i++) {
        f[i][1] = 1;
    }
    for (int i = 2; i <= k; i++) {
        f[i][i] = 1;
        for (int j = i + 1; j <= n; j++) {
            f[j][i] += f[j - 1][i - 1] + f[j - i][i];
        }
    }
    printf("%d", f[n][k]);
    return 0;
}

2.组合数的输出

点击查看代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int n,m,a[100];
bool b[100]; 
void print()
{
	for(int i=1;i<=m;i++)printf("%d ",a[i]);
	printf("\n");
	return;
}
int dfs(int x,int y)
{
	if(y>m) print();
	else
	{
		for(int i=x;i<=n;i++)
		{
			a[y]=i;
			dfs(i+1,y+1);
		}
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	dfs(1,1);
	return 0;
}

3.拔河比赛
详见Ybtoj

当然重点在于搜索都配有板子了

点击查看1
int search(int k)
{
	for(int i=1;i<=n;i++)
	{
		if()//合法 
		{
			//保存 
			if()//终点 
			{
				ans++;
				print();
			}
			else search(++k);
		}
		//恢复(回溯) 
	}
}
点击查看2
int search(int k)
{
	if()//
	{
		ans++;
		print();
	}
	else for(int i=1;i<=n;i++)
	{
		if()
		{
			//
			search(++k);
			//
		}
	}
}

注意场宽 && STL大法好

题目描述

第一行:n
第二行:n个字符(有重复)
输出:全排列+方案数
思路:把单一的 vis[i] 换为累加器数组

STL大法好
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string.h>
#include<algorithm>
int n;
char s[30];
int main()
{
    long long ans = 0;
    scanf("%d",&n);
    scanf("%s",s+1);
    std::sort(s+1,s+n+1);
    do{
        for(int i=1;i<=n;i++) printf("%c",s[i]);
        printf("\n");
        ++ans;
    }while(std::next_permutation(s+1,s+n+1));
    printf("%lld\n", ans);
    return 0;
}

正解
#include <iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string.h>
using namespace std;
int n , ans = 0;
char s[100];
bool same( int t, int k) {
    for(int i = t; i < k; ++i) {
        if(s[k] == s[i]){
            return 0;
        }
    }
    return 1;
}
void print()
{
    for(int i = 0; i < n; i++) {
        printf("%c",s[i]);
    }
    printf("\n");
}
void dfs(int t) {
    if(t == n-1) {
        print();
        ans++;
    }
    for(int i = t; i < n; ++i){
        if(same(t, i)) {
            swap(s[i], s[t]);
            dfs( t + 1 );
            swap(s[i], s[t]);
        }
    }
}
int main() {
    scanf("%d",&n);
    cin >> s;
    dfs( 0);
    printf("%d",ans);
    return 0;
}
//数组尽量开大一点
posted @ 2022-01-23 10:50  fervency  阅读(29)  评论(0编辑  收藏  举报