枚举例题

如果你不知道什么是枚举:传送门

P2089

猪猪 Hanke 特别喜欢吃烤鸡(本是同畜牲,相煎何太急!)Hanke 吃鸡很特别,为什么特别呢?因为他有 10 10 10种配料(芥末、孜然等),每种配料可以放 1 1 1 3 3 3克,任意烤鸡的美味程度为所有配料质量之和。现在, Hanke 想要知道,如果给你一个美味程度 n n n,请输出这 10 10 10种配料的所有搭配方案。

输入格式
一个正整数 n n n,表示美味程度。 n ≤ 5000 n \leq 5000 n5000

输出格式
第一行,方案总数
第二行至结束, 10 10 10个数,表示每种配料所放的质量,按字典序排列。
如果没有符合要求的方法,就只要在第一行输出一个 0 0 0

输入样例
11

输出样例
10
1 1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 2 1
1 1 1 1 1 1 1 2 1 1
1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 2 1 1 1 1
1 1 1 1 2 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1
1 1 2 1 1 1 1 1 1 1
1 2 1 1 1 1 1 1 1 1
2 1 1 1 1 1 1 1 1 1

思路:这是一个典型的暴力枚举题,因为数据范围很小,我们只需要十个嵌套for循环,枚举每一种可能即可。

#include 
using namespace std;
typedef long long ll;
#define endl '\n'
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
const int INF = 0x7fffffff;


int main() {  
    int a, b, c, d, e, f, g, h, i, j, n, res=0;  
    cin >> n;  
    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 == n) {  
                                                res++;  
                                            }  
                                        }  
                                    }  
                                }  
                            }  
                        }  
                    }  
                }  
            }  
        }  
    }  
    cout << res << endl;  
    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 == n) {  
                                    			cout << a << " " << b << " "; 
                                                 cout << c << " " << d << " ";
                                                 cout << e << " " << f << " ";
                                   				cout << g << " " << h << " ";
                                                 cout << i << " " << j << endl; 
                                            }  
                                        }  
                                    }  
                                }  
                            }  
                        }  
                    }  
                }  
            }  
        }  
    }  
	return 0;  
}  

P3654 First Step (ファーストステップ)

输入 n , m , k n,m,k n,m,k,输入一个 n × m n\times m n×m的字符矩阵,输出其中可以让 k k k人排成一排的空位数,行列皆可。 n , m ≤ 100 , k < m i n ( n , m ) n,m\leq 100, k < min(n,m) n,m100,k<min(n,m)

思路:题目中的数据范围很小,我们可以直接枚举,从每一个点开始,横向和竖向搜索 k k k位,如果没有碰到任何障碍,答案加 1 1 1,当然我们需要特殊考虑当 k = 1 k=1 k=1时,横向和竖向是一样的,这相当于我们计算量两次,所以需要特判并输出答案 / 2 /2 /2

#include 
using namespace std;
typedef long long ll;
#define endl '\n'
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
const int INF = 0x7fffffff;

int n, m, k, res;
char ch[110][110];

int main(){
	cin >> n >> m >> k;
	for(int i = 1;  i <= n; i++){
		for(int j = 1; j <= m; j++){
			cin >> ch[i][j];
		} 
	}
	for(int i = 1; i <= n; i++){//横向判断
		for(int j = 1; j <= m; j++){
			if(ch[i][j] != '#'){
				bool b = true;
				for(int a = 0; a < k; a++){
					if(ch[i][j+a] != '.'){
						b = false;
						break;
					} 
				}
				if(b) res++;
			}
		}
	}
	for(int i = 1; i <= n; i++){//竖向判断
		for(int j = 1; j <= m; j++){
			if(ch[i][j] != '#'){
				bool b = true;
				for(int a = 0; a < k; a++){
					if(ch[i+a][j] != '.'){
						b = false;
						break;
					} 
				}
				if(b) res++;
			}
		}
	}
	if(k == 1) cout << res / 2 << endl;//特判当k=1
	else cout << res << endl;
	return 0;
}

P3392涂国旗

某国法律规定,只要一个由 N × M N\times M N×M个小方块组成的旗帜符合如下规则,就是合法的国旗。

  • 从最上方若干行(至少一行)的格子全部是白色的;
  • 接下来若干行(至少一行)的格子全部是蓝色的;
  • 剩下的行(至少一行)全部是红色的;

现有一个棋盘状的布,分成了 N N N M M M 列的格子,每个格子是白色蓝色红色之一,小 a 希望把这个布改成该国国旗,方法是在一些格子上涂颜料,盖住之前的颜色。小a很懒,希望涂最少的格子,使这块布成为一个合法的国旗。

输入格式

第一行是两个整数 N N N, M M M N , M ≤ 50 N,M \leq 50 N,M50
接下来 N N N行是一个矩阵,矩阵的每一个小方块是W(白),B(蓝),R(红)中的一个。

输出格式

一个整数,表示至少需要涂多少块。

输入样例 输出样例
4 5 11
WRWRW
BWRWB
WRWRW
RWBWR

思路:我们知道数据范围很小,所以果断选择暴力枚举。根据题目,我们可以这样开三个数数组 W [ i ] , B [ i ] , R [ i ] W[i],B[i],R[i] W[i],B[i],R[i]分别表示前 i i i行涂成白、蓝、红需要的格子数。假设第 1 1 1行到第 i i i行是白色,第 i + 1 i+1 i+1行到第 j j j行是蓝色,第 j + 1 j+1 j+1行到第 n n n行是红色,则此时的需要涂的格子为 W [ i ] + B [ j ] − B [ i ] + R [ n ] − R [ j ] W[i] + B[j]-B[i]+R[n]-R[j] W[i]+B[j]B[i]+R[n]R[j]。我们只需要枚举 i , j i,j i,j,取最小值即可。

#include 
using namespace std;
typedef long long ll;
#define endl '\n'
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
const int INF = 0x7fffffff;

int n, m, res = INF;
string str;
int W[55], B[55], R[55];

inline int check(char ch){
	int res = 0;
	for(int i = 0; i < m; i++){
		if(str[i] != ch) res++;
	}
	return res;
}

int main(){
	cin >> n >> m;
	for(int i = 1; i <= n; i++){
		cin >> str;
		W[i] = W[i-1] + check('W');
		B[i] = B[i-1] + check('B');
		R[i] = R[i-1] + check('R');
	}
	for(int i = 1; i < n - 1; i++){
		for(int j = i + 1; j < n; j++){
			res = min(res,W[i]+B[j]-B[i]+R[n]-R[j]);
		}
	}
	cout << res << endl;
	return 0;
} 

P1149火柴棒等式

​ 给你 n n n根火柴棍,你可以拼出多少个形如 A + B = C A+B=C A+B=C的等式?等式中的 A A A B B B C C C是用火柴棍拼出的整数(若该数非零,则最高位不能是 0 0 0)。
​ 注意:

  1. 加号与等号各自需要两根火柴棍
  2. 如果$A\neq B ,则 ,则 ,则A+B=C 与 与 B+A=C 视为不同的等式 视为不同的等式 视为不同的等式(A,B,C\geq 0)$。
  3. n n n根火柴棍必须全部用上

输入格式:一个整数 n n n ( n ≤ 24 ) (n \leq 24) (n24)

输出格式:一个整数,能拼成的不同等式的数目。

思路:因为最多只有 20 20 20根火柴用来拼三个数字,所以我们只需要记录 1 1 1 1000 1000 1000内所有数字是用火柴数。

#include 
using namespace std;
typedef long long ll;
#define endl '\n'
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
const int INF = 0x7fffffff;

int main()
{
	int arr[2001]={6},n,src[10]={6,2,5,5,4,5,6,3,7,6},sum,i,j;
	cin>>n;
	for(i=1;i<=2000;i++)
	{
		j=i;
		while(j>=1)
		{
			arr[i]+=src[j%10];
			j/=10;
		}
	}
	for(i=0;i<1000;i++)
		for(j=0;j<1000;j++)
			if(arr[i]+arr[j]+arr[i+j]+4==n) sum++;
	cout<

你可能感兴趣的:(例题,c++,算法,开发语言)