如果你不知道什么是枚举:传送门
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 n≤5000输出格式
第一行,方案总数
第二行至结束, 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,m≤100,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,M≤50
接下来 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)。
注意:
- 加号与等号各自需要两根火柴棍
- 如果$A\neq B ,则 ,则 ,则A+B=C 与 与 与B+A=C 视为不同的等式 视为不同的等式 视为不同的等式(A,B,C\geq 0)$。
- n n n根火柴棍必须全部用上
输入格式:一个整数 n n n ( n ≤ 24 ) (n \leq 24) (n≤24)。
输出格式:一个整数,能拼成的不同等式的数目。
思路:因为最多只有 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<