洛谷题单【算法1-3】暴力枚举(STL应用cpp版)

本蒟蒻又来写blog~~er辣!!!

最近一直在练搜索学不懂啊啊啊。。。

发现枚举大多利用dfs解决,专属骗分技巧,题单上枚举题很多正解都是dfs呢。

要不总结总结????

→大脑cpu爆啦。。。

【算法1-3】暴力枚举 - 题单 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)icon-default.png?t=N7T8https://www.luogu.com.cn/training/108

一,经典问题详解:

1.全排列:

例1:P1706:  P1706 全排列问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

按照字典序输出自然数 11 到 n 所有不重复的排列,即n的全排列,要求所产生的任一数字序列中不允许出现重复的数字。

输入:一个整数 n。

输出:由 1∼n 组成的所有不重复的数字序列,每行一个序列。每个数字保留 5 个场宽。

应该算是经典题了,

STL有一个很有用的函数next_permutation,用于求一个序列的下一个字典序排列

存在于头文件:

#include<algorithm>

基本用法:

next_permutaion(起始地址,末尾地址+1)
next_permutaion(起始地址,末尾地址+1,自定义排序)

默认升序,可自定义,和sort一样呢。

更改这个序列,让它成为下一个字典序排列,并返回一个 bool 值,表示是否成功生成下一个排列。当序列已经是字典序最大的排列时,不再存在下一个排列,函数将返回 false。

专门解决本题的函数。。。

利用STL解决本题很快呢:

#include <iostream>
#include<algorithm>
#include<vector> 
#include<cstdio>
using namespace std;
int n;
int main()
{
    cin>>n;
	vector<int> a;
	
	for(int i=1;i<=n;i++)
	a.push_back(i);
	
	do{	
		for(int i=0;i<a.size();i++)
		printf("%5d ",a[i]);//注意格式 
		cout<<endl;
	}while(next_permutation(a.begin(), a.end()));//生成排列,当生成字典序最大的排列时结束 
	
	return 0;
	
}

太简单了是吧qwq,如果蒟蒻不知道这个函数咋整?(next_permutation啥啊。。。)

分析一下:若我们一个一个枚举排列,有两点考虑。

1.枚举到何位置?

我们可以定义一个位置数组存放解,当位置到达上限时停止。

2.位置上放啥数字?

全排列数字要求不能重复,当选择了一个数字后加入位置数组后就不能再用了,于是我们可以定义一个状态数组判断是否使用,避免重复。

当然方案很多,这个状态数组排完一个方案后又要去找下一个方案,需要重置,这个就是回溯。

综上所述,设置几个变量

int n;//总数
bool book[100];//状态数组,标记数字是否使用,没使用为0,注意回溯 
int a[100];//位置数组 

主要计位置,位置为一个边界条件,利用位置判断返回or不返回

于是

void dfs(int step) //用来表示当前处理到了全排列的第几个位置

设位置从1开始,当位置到n+1时结束,输出结果。

//边界条件**********************************//	
	
	if(step==n+1)//这里说明前面的n个位置已经放好了,这是dfs结束的标志  
	{
		for(int i=1;i<=n;i++)
			printf("%5d",a[i]);//注意格式 
		printf("\n");
		
		return;
		/* 
		注意这个 return 它的作用不是返回主函数,而是返回上一级的dfs函数
		
		例:如果此时是  dfs(5),遇到这个 return 就会回到上一级的 dfs函数 
		也就是dfs(4),但此时dfs(4)的大部分语句已经执行了,只需要接着执行 book[i]=0
		然后继续进入for循环进入下一次的 dfs函数,直到结束。 		
		*/ 
	}

进入递归,依次枚举每个位置的数字,首先确定数字是否用过,没用过用了标记,递归完后复原。

//进行步骤*********************************//	
	for(int i=1;i<=n;i++)
	{
		if(book[i]==0)//如果未使用该数字 
		{   
			a[step]=i;//使用数字 
			book[i]=1;//标记已经使用 
			
			dfs(step+1);//进行下一个 
			
			book[i]=0;//回溯!!!!重点 
		}
	}
	return;//这里表示这一级别的dfs函数已经结束了,返回上一级 dfs函数 
}

上总代码:qwq

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>  
using namespace std;

int n;
bool book[100];//标记数字是否使用,没使用为0,注意回溯 
int a[100];//数据存入数组 


void dfs(int step) //用来表示当前处理到了全排列的第几个位置
{

//边界条件**********************************//	
	
	if(step==n+1)//这里说明前面的n个位置已经放好了,这是dfs结束的标志  
	{
		for(int i=1;i<=n;i++)
			printf("%5d",a[i]);//注意格式 
		printf("\n");
		
		return;
		/* 
		注意这个 return 它的作用不是返回主函数,而是返回上一级的dfs函数
		
		例:如果此时是  dfs(5),遇到这个 return 就会回到上一级的 dfs函数 
		也就是dfs(4),但此时dfs(4)的大部分语句已经执行了,只需要接着执行 book[i]=0
		然后继续进入for循环进入下一次的 dfs函数,直到结束。 		
		*/ 
	}

//进行步骤*********************************//	
	for(int i=1;i<=n;i++)
	{
		if(book[i]==0)//如果未使用该数字 
		{   
			a[step]=i;//使用数字 
			book[i]=1;//标记已经使用 
			
			dfs(step+1);//进行下一个 
			
			book[i]=0;//回溯!!!!重点 
		}
	}
	return;//这里表示这一级别的dfs函数已经结束了,返回上一级 dfs函数 
}
int main()
{
    
    ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	cin>>n;

	dfs(1); //进入dfs 
	return 0;
}

这里友好地中肯地附上伪代码,一定要细心理解!

//要理解dfs的关键在于解决当下该怎么做和下一步如何做
void dfs(int step)
{
    判断边界

	尝试每一种可能 for(i=1;i<=n;i++)
	{
		继续下一步 dfs(step+1)
	}
	
    返回
}
 //基本模板放上哒 

例2:P2089 烤鸡 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

让我想起了某位故人。。。。

这道题依然可以暴力枚举(嵌套的for实在是吓人qwq)

#include<cstdio> 
#include<iostream>
using namespace std;
void g(int x)
{
	int q=0;
	int a,b,c,d,e,f,g,h,i,j;
	for(a=1;a<=3;a++)
		for(b=1;b<=3;b++)
			for(c=1;c<=3;c++)
				for(d=1;d<=3;d++)
					for(e=1;e<=3;e++)
						for(f=1;f<=3;f++)
							for(g=1;g<=3;g++)
								for(h=1;h<=3;h++)
									for(i=1;i<=3;i++)
										for(j=1;j<=3;j++)
										{
									      if(a+b+c+d+e+f+g+h+i+j==x)
									       q++;
										}
	
printf("%d\n",q);		
}

void f(int x)
{
	int a,b,c,d,e,f,g,h,i,j;
	for(a=1;a<=3;a++)
		for(b=1;b<=3;b++)
			for(c=1;c<=3;c++)
				for(d=1;d<=3;d++)
					for(e=1;e<=3;e++)
						for(f=1;f<=3;f++)
							for(g=1;g<=3;g++)
								for(h=1;h<=3;h++)
									for(i=1;i<=3;i++)
										for(j=1;j<=3;j++)
										{
									      if(a+b+c+d+e+f+g+h+i+j==x)
									      printf("%d %d %d %d %d %d %d %d %d %d\n",a,b,c,d,e,f,g,h,i,j);
										}
	
	
	
	
}

int main()
{
	int a;
	scanf("%d",&a);
	if(a>30||a<10)
	printf("0\n");
	else
	g(a);
	f(a);
	
	
return 0;	
	
}

呐呐,代码恐怖噻。。都嵌套了为啥不用搜索,递归搜索呐!(˚ ˃̣̣̥᷄⌓˂̣̣̥᷅ )。。

首先是有10个位置放调料,总调料质量要刚好分配完。。。两个变量

于是dfs为

int n;//总质量
int kind=0;//记方案数量 
int arr[10];//记方案 
int m[10000][10];//存入方案全部 

void dfs(int total,int a)//a为枚举到了哪个调料,total为已选调料的总质量 

 分析dfs的边界,满足10个位置且总质量分配好后完成一种方案

于是边界为

 if(a==10)//边界条件 
	{
        if (total==n)
		{
            for(int j=0;j<10;j++) 
			m[kind][j]=arr[j];//存入方案 
            
			kind++;//计数量 
        }
        return; 
    }
    
if(total>n) return;//剪枝优化,当总质量超过限制时返回上一层 

每个位置枚举质量,枚举要么1要么2要么3.。。

于是进入递归为

	 for(int i=1;i<=3;i++)
		{
          arr[a]=i;
          dfs(total+i,a+1);//入递归 
    	}

甭废话,上代码:

//依次枚举每个调料可以放多少 
//指数级枚举 
#include<iostream>
#include<cmath>
#include<string>
#include<vector>
#include<cstdio> 
#define ll long long
#define llu long long unsigned
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;

int n;//总质量
int kind=0;//记方案数量 
int arr[10];//记方案 
int m[10000][10];//存入方案全部 

void dfs(int total,int a)//a为枚举到了哪个调料,total为已选调料的总质量 
{
    if(a==10)//边界条件 
	{
        if (total==n)
		{
            for(int j=0;j<10;j++) 
			m[kind][j]=arr[j];//存入 
            
			kind++;//计数量 
        }
        return; 
    }
    if(total>n) return;//剪枝,当总质量超过限制时返回上一层 
   
  
    	 for(int i=1;i<=3;i++)
		{
          arr[a]=i;
          dfs(total+i,a+1);//入递归 
    	}
	
}
int main()
{
    IOS
	cin>>n;
   	dfs(0,0);
    cout<<kind<<endl;
    
	for(int j=0;j<kind;j++)
	{
      	for(int i=0;i<10;i++) 
		cout<<m[j][i]<<" "; 
		 
    	cout<<endl; 
    }
    return 0;
}

2.组合:

例1:P1157:P1157 组合的输出 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

组合也就把排列中有相同数字的去重了,利用STL的next_permutation函数排列一个包含r个0,长度为n的bool型数组,需要输出的设为0,只输出bool数组中为0的下标即可。。。

利用STL解决:

#include<iostream>
#include<algorithm>
#include<string>
#include<queue> 
using namespace std;
#define long long ll
#define unsigned long long ull
bool s[100010];
int main()
{
	int n,r;
	cin>>n>>r;
	
	for(int i=r+1;i<=n;i++)
	s[i]=1;//保留r个0,下标从1开始 
	
	do{
		for(int i=1;i<=n;i++)
		{
			if(s[i]==0)
			printf("%3d", i); //如果s[i]为0,则输出该数字,注意格式。 
    	}
			printf("\n"); // 换行
	
	}while(next_permutation(s+1,s+n+1));
	
	return 0;
}

感觉上面的写法很有技巧呢。。。来看看搜索。。

还是要考虑两个问题:

1.枚举到何位置?

我们和全排列一样可以定义一个位置数组存放解,当位置到达上限时停止。

2.位置上放啥数字?

数字要求不能重复,但同时还要求每种组合中保证出现的数字不能全一样。。。

于是我们可以用一个变量来记录选取的数字是哪个,一个一个选,把含有这个数字所有组合方案输出来,之后就不选了呗

这样我们的dfs:

int n,r;
int a[200];

void dfs(int step,int next)//next表示下一步选取的数字开始 

边界与递归步骤同理,直接上代码:

#include<iostream>
#include<string>
#include<queue> 
#define long long ll
#define unsigned long long ull
using namespace std;

int n,r;
int a[200];

void dfs(int step,int next)//next表示下一步选取的数字开始 
{
	if(step==r+1)
	{
		for(int i=1;i<=r;i++)
			printf("%3d",a[i]); //输出当前的组合
		printf("\n");
		
		return;
	}
	
	for(int i=next;i<=n;i++) //从next开始遍历可选的数字
	{
		a[step]=i; //将数字i加入当前组合
		dfs(step+1,i+1); //继续递归选择下一个数字,下一个数字从i+1开始 
	} 
	return;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	
	cin>>n>>r;
	dfs(1,1);
	
	return 0;
}

例2:P1036 P1036 [NOIP2002 普及组] 选数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 

关于暴力枚举就不多介绍了,不过社区中还真有人这样做(○´・д・)ノ,把蒟蒻吓哭了。。。

对比明显了吧◕‿◕。。。

也变向为组合问题的一种,各种方案选取的所有数字不能完全一样,就加了个判断素数。。。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<vector>
#define ll long long 
using namespace std;
bool findprime(ll n)
{
	ll i;
	if(n==1||n==0)
	return 0;
	for(i=2;i*i<=n;i++)
		if(n%i==0)
			return 0;
	return 1;	
}//判断素数,算基础了不说了哒哒哒。。。

ll s[100];//存可以选的数
ll n,m,cn;//n为可以选的数的数量,m为要选几个数,cn为方案总数

void dfs(int x,int sum,int start)//x为选到第几个数,sum为选到数的和,从start遍历选数
{
 	if(x==m)//边界条件
	{
		if(findprime(sum))//是素数就入方案
		cn++;	

		return; //返回
	}
	 
	for(int i=start;i<n;i++)
        dfs(x+1,sum+s[i],i+1);//从start开始入递归 

}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	
	cin>>n>>m;
	
	for(ll i=0;i<n;i++)
	cin>>s[i];
	
	dfs(0,0,0);//入递归
	cout<<cn;

	return 0;
	
}

3.处理图:

例1:P3654:First Step (ファーストステップ) - 洛谷

典型图搜索问题,算最好理解的呢qwq,不过有坑。。。(宕机(灬ꈍ ꈍ灬))

思路就是判断每一个点向下和向右是否能满足条件(或者向下向左、向上向右、向上向左,一定不是向上向下或向左向右!!!),但是r=1时需要特判,因为r=1意味着向下和向右重复计算,需要除以2。(要不然只能得WA80辣!)。

还有就是lovelive! sunshine !  但是BanG Dream!Is's MyGO!启动(*❦ω❦)!!!

上代码:

#include<iostream> 
#include<cstdio>

using namespace std;
#define ll long long
#define llu long long unsigned
#define pq priority_queue
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
const int N=1e3+10;
int n,m,r;
int dx[2]={0,1},dy[2]={-1,0};//两个方向 
char mp[1001][1001];
int ans;
void dfs(int x,int y,int cn,int sum)
{
	if(sum>r)//符合条件记录,返回上一层 
	{
		ans++;
		return;
	}
	if(x<0||y<0||x>=n||y>=m||mp[x][y]!='.')//边界返回上一层 
	return;
	

	dfs(x+dx[cn],y+dy[cn],cn,sum+1);
		
	
}
int main()
{
	IOS
	cin>>n>>m>>r;
	for(int i=0;i<n;i++)
	cin>>mp[i];
	
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			if(mp[i][j]=='.') 
				for(int k=0;k<2;k++)
					dfs(i,j,k,1);//两个方向进入dfs 
			
	if(r==1)//特判 
	cout<<ans/2;
	else
	cout<<ans;
	return 0;
}

二,刷洛谷(又🤮)

赶紧给大家讲解(粘代码)

P1149 P1149 [NOIP2008 提高组] 火柴棒等式 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

我滴火柴人。。。

#include <iostream>
#include <algorithm>
#include <cstdio>
#define ll long long
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;

// 火柴棍数目对应的数字所需火柴棍数目
int n[10] = {6, 2, 5, 5, 4, 5, 6, 3, 7, 6};
int N; // 目标数字所需的总火柴棍数目
int res; // 符合条件的方案数量
int arr[3], s[2050]; // arr数组用于存储当前选取的数字,s数组用于存储每个数字所需的火柴棍数目

void dfs(int pos, int sum)
{
    if (sum > N)  // 如果当前火柴棍数目已经超过目标数,则结束当前递归
        return;
    
    if (pos >= 3) // 当前已选取了3个数字
    {
        if (arr[0] + arr[1] == arr[2] && sum == N) // 满足条件:前两个数字之和等于第三个数字,并且火柴棍数目达到目标数
            res++; // 方案数加一

        return;
    }

    for (int i = 0; i <= 710; i++)
    {
        arr[pos] = i; // 尝试选取数字i
        dfs(pos + 1, sum + s[i]); // 递归选择下一个数字,并更新火柴棍数目总和
        arr[pos] = 0; // 回溯,取消选择数字i
    }
}

int main()
{
    IOS
    cin >> N;
    N -= 4; // 减去“four”的火柴棍数目

    for (int i = 0; i <= 1000; i++) 
    {
        int x = i;
        if (x == 0)
            s[i] = n[x];
        else
        {
            while (x != 0) 
            {
                s[i] += n[x % 10]; // 计算数字i所需的火柴棍数目
                x /= 10;
            }
        }
    }

    dfs(0, 0); // 从第一个位置开始深度优先搜索

    cout << res; // 输出符合条件的方案数量
    return 0;
}

P2036 P2036 [COCI2008-2009 #2] PERKET - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

条件多了些而已。。。没啥区别。。

#include <cstdio>
#include <cmath>
#include <iostream>
using namespace std;

int n; // 物质数量
int acid[20], bitter[20]; // 酸度和苦味数组
int res = 1e9; // 记录最小差值

void dfs(int idx, int acidsum, int bittersum)
{
    if (idx == n) // 遍历完所有物质
    {
        if (acidsum != 1 && bittersum != 0) // 排除初始值情况
        {
            res = min(res, abs(acidsum - bittersum)); // 更新最小差值
        }
        return;
    }

    // 选择当前元素
    dfs(idx + 1, acidsum * acid[idx], bittersum + bitter[idx]);

    // 不选择当前元素
    dfs(idx + 1, acidsum, bittersum);
}

int main()
{
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        scanf("%d %d", &acid[i], &bitter[i]); // 输入各物质的酸度和苦味值
    }
    
    dfs(0, 1, 0); // 从第一个元素开始递归,初始酸度为1,初始苦味为0
    cout << res; // 输出最小差值
    return 0;
}

P1088:P1088 [NOIP2004 普及组] 火星人 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

还是搜索全排列问题,这次是记录排列数量,本题还有中方法叫康托展开,感兴趣朋友们自查,本蒟蒻还不会呢。。。。

直接上dfs代码:

#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <cstdio>
#define ll long long
#define llu long long unsigned
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define N 10010
using namespace std;

int n, m;
int arr[N]; // 记录方案
int mars[N]; // 记录火星人排列
bool st[N]; // 记录选择的数字
int res = 0; // 记录次数
bool stop = 0; // 停止

void dfs(int x) // DFS函数,x表示当前位置
{
    if (stop)
        return;

    if (x > n)
    {
        res++;
        if (res == m + 1)
        {
            stop = 1;
            for (int i = 1; i <= n; i++)
                cout << arr[i] << " ";
        }
        // return;
    }

    for (int i = 1; i <= n; i++)
    {
        if (!res)
            i = mars[x];

        if (!st[i])
        {
            st[i] = 1; // 标记数字i被选择

            arr[x] = i; // 在第x个位置选择数字i
            dfs(x + 1); // 递归到下一个位置

            st[i] = 0; // 回溯,取消选择数字i
            arr[x] = 0;
        }
    }
}

int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        cin >> mars[i];

    dfs(1); // 从第一个位置开始进行深度优先搜索

    return 0;
}

P1618:P1618 三连击(升级版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

升级咯。。。。

利用next_permutation函数可以完美解决

#include<cstdio> 
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define llu long long unsigned
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define pq priority_queue
const int N=1e9+10;
int s[9]={1,2,3,4,5,6,7,8,9};
ll sum=0;
int main()
{
	IOS
	int a,b,c;
	cin>>a>>b>>c;
	do{
		ll x=s[0]*100+s[1]*10+s[2];
		ll y=s[3]*100+s[4]*10+s[5];
		ll z=s[6]*100+s[7]*10+s[8];
		if(x*b==y*a&&x*c==z*a&&y*c==z*b)
		{
			sum++;
			cout<<x<<" "<<y<<" "<<z<<endl;
		}
	
	}while(next_permutation(s,s+9));
	if(!sum)
	cout<<"No!!!\n";
	return 0;
}

P2241: P2241 统计方形(数据加强版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

正解是数学问题。。。画画图就明白了。。。。

#include <iostream>
#include<cstdio>
#include<cmath>
#define ll long long
using namespace std;
int main() 
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	ll n,m,sum1=0,sum2=0;
	cin>>n>>m;
	
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
		{
			if(i==j)
			sum1+=(n-i)*(m-j);//i==j就是正方形
			else
			sum2+=(n-i)*(m-j);//不是为矩形
		}
	
	cout<<sum1<<" "<<sum2;
	return 0;
}

P3392:P3392 涂条纹 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

简单题直接枚举,搜索反而麻烦。。。

#include<iostream>
#include<cstdio>

using namespace std;
#define  N 666666
 
int n,m,i,j,k,g;
char arr[55][55];   
int ans=N;
 
int main()
{
	scanf("%d%d",&n,&m);
	
	for (i=1;i<=n;i++)
	{
		for (j=1;j<=m;j++)
		{
			cin>>arr[i][j];
		}
	}
	
	for (i=1;i<=n-2;i++)    
		for (j=i+1;j<=n-1;j++)
		{
			int sum=0;
			for (k=1;k<=i;k++)
				for (g=1;g<=m;g++)
					if (arr[k][g]!='W') 
						sum++;
			
			for (int k = i + 1; k <= j; k++)
				for (int g = 1; g <= m; g++)
					if (arr[k][g] != 'B') 	
						sum++;
			
			for (int k = j + 1; k <= n; k++)
				for (int g = 1; g <= m; g++)
					if (arr[k][g] != 'R') 
						sum++;
			
			if (sum < ans)
				ans = sum;
		}
	printf("%d\n", ans);
	return 0;
}

P1217: 

P1217 [USACO1.5] 回文质数 Prime Palindromes - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

枚举就能做。。。

#include <iostream>
#include <cmath>
#include <vector>
#define ll uint64_t
using namespace std;

bool isPrime(ll n, const vector<bool>& primes) 
{
    if (n <= 1) return false;
    if (n == 2) return true;
    if (n % 2 == 0) return false;
    return primes[n];
}

bool isPalindrome(ll n)
{
    ll num = n, rev = 0;
    while (num > 0)
    {
        rev = rev * 10 + num % 10;
        num /= 10;
    }
    return n == rev;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    ll n, m;
    cin >> n >> m;

    // 预处理质数表
    vector<bool> primes(m + 1, true);
    primes[0] = primes[1] = false;
    for (ll i = 2; i * i <= m; ++i)
    {
        if (primes[i])
        {
            for (ll j = i * i; j <= m; j += i)
            {
                primes[j] = false;
            }
        }
    }

    if (n <= 2 && m >= 2) cout << "2\n";
    if (n % 2 == 0) n++;

    for (ll i = n; i <= m; i ++)
    {
        if (isPalindrome(i) && isPrime(i, primes))
        {
            cout << i << "\n";
        }
    }

    return 0;
}

 P2392:P2392 kkksc03考前临时抱佛脚 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

不要认为是贪心了呢。。。。

#include<bits/stdc++.h>
using namespace std;

int Left, Right, minn, ans; // 左侧总和、右侧总和、当前最小差值、答案
int s[5]; // 每个集合的元素数量
int a[21][5]; // 存储每个元素的值

void dfs(int x, int y)
{
    if(x > s[y])
{
        minn = min(minn, max(Left, Right)); // 更新最小差值
        return;
}
    Left += a[x][y];
    dfs(x + 1, y); // 选择当前元素
    Left -= a[x][y];
    
    Right += a[x][y];
    dfs(x + 1, y); // 不选择当前元素
    Right -= a[x][y]; // 回溯
}

int main()
{
    cin >> s[1] >> s[2] >> s[3] >> s[4]; // 输入每个集合的元素数量
    for(int i = 1; i <= 4; i++)
{
        Left = Right = 0;
        minn = 19260817; // 初始化最小差值为一个较大的数
        for(int j = 1; j <= s[i]; j++)
            cin >> a[j][i]; // 输入每个元素的值
        dfs(1, i); // 开始搜索
        ans += minn;
}
    cout << ans; // 输出答案
    return 0;
}

好了,第二篇就到这里了,

搜索折磨死我了哇哇哇哇。。。。

下篇再见呢!!!!!

  • 21
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值