c++枚举例题

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

P2089

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

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

输出格式
第一行,方案总数
第二行至结束,\(10\)个数,表示每种配料所放的质量,按字典序排列。
如果没有符合要求的方法,就只要在第一行输出一个\(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 <bits/stdc++.h>
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\times m\)的字符矩阵,输出其中可以让\(k\)人排成一排的空位数,行列皆可。\(n,m\leq 100, k < min(n,m)\)

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

#include <bits/stdc++.h>
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\times M\)个小方块组成的旗帜符合如下规则,就是合法的国旗。

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

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

输入格式

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

输出格式

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

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

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

#include <bits/stdc++.h>
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\)根火柴棍,你可以拼出多少个形如\(A+B=C\)的等式?等式中的\(A\)\(B\)\(C\)是用火柴棍拼出的整数(若该数非零,则最高位不能是\(0\))。
​ 注意:

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

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

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

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

#include <bits/stdc++.h>
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<<sum<<endl;
	return 0;
 }  
posted @ 2021-04-21 08:54  h星宇  阅读(339)  评论(0编辑  收藏  举报