1、
1317:【例5.2】组合的输出
时间限制: 1000 ms 内存限制: 65536 KB
提交数:52237 通过数: 26231
【题目描述】
排列与组合是常用的数学方法,其中组合就是从n个元素中抽出r个元素(不分顺序且r≤n),我们可以简单地将n个元素理解为自然数1,2,…,n,从中任取r个数。
现要求你用递归的方法输出所有组合。
例如n=5,r=3,所有组合为:
1 2 3 1 2 4 1 2 5 1 3 4 1 3 5 1 4 5 2 3 4 2 3 5 2 4 5 3 4 5
【输入】
一行两个自然数n、r(1<n<21,1≤r≤n)。
【输出】
所有的组合,每一个组合占一行且其中的元素按由小到大的顺序排列,每个元素占三个字符的位置,所有的组合也按字典顺序。
【输入样例】
5 3
【输出样例】
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
#include<iostream>
#include<iomanip>
using namespace std;
int n,r;
int a[110];
void dfs(int cur,int pre)
{
if(cur==r)
{
for(int i=0;i<r;i++)
{
cout<<setw(3)<<a[i];
}
cout<<endl;
return ;
}
for(int i=pre+1;i<=n;i++)
{
a[cur]=i;
dfs(cur+1,i);
}
}
int main()
{
cin>>n>>r;
dfs(0,0);
return 0;
}
2、
1318:【例5.3】自然数的拆分
时间限制: 1000 ms 内存限制: 65536 KB
提交数:37561 通过数: 21969
【题目描述】
任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和。
当n=7共14种拆分方法:
7=1+1+1+1+1+1+1
7=1+1+1+1+1+2
7=1+1+1+1+3
7=1+1+1+2+2
7=1+1+1+4
7=1+1+2+3
7=1+1+5
7=1+2+2+2
7=1+2+4
7=1+3+3
7=1+6
7=2+2+3
7=2+5
7=3+4
total=14
【输入】
输入n。
【输出】
按字典序输出具体的方案。
【输入样例】
7
【输出样例】
7=1+1+1+1+1+1+1
7=1+1+1+1+1+2
7=1+1+1+1+3
7=1+1+1+2+2
7=1+1+1+4
7=1+1+2+3
7=1+1+5
7=1+2+2+2
7=1+2+4
7=1+3+3
7=1+6
7=2+2+3
7=2+5
7=3+4
#include<iostream>
using namespace std;
int n;
int a[10010]={1};
void dfs(int cur,int n1)
{
if(n1>n)
{
return ;
}
if(n1==n)
{
cout<<n1<<"="<<a[1];
for(int i=2;i<cur;i++)
{
cout<<"+"<<a[i];
}
cout<<endl;
return;
}
for(int i=a[cur-1];i<n;i++)
{
a[cur]=i;
dfs(cur+1,n1+i);
}
}
int main()
{
cin>>n;
dfs(1,0);
return 0;
}
3、
1212:LETTERS
时间限制: 1000 ms 内存限制: 65536 KB
提交数:43806 通过数: 20134
【题目描述】
给出一个row×col���×���的大写字母矩阵,一开始的位置为左上角,你可以向上下左右四个方向移动,并且不能移向曾经经过的字母。问最多可以经过几个字母。
【输入】
第一行,输入字母矩阵行数R�和列数S�,1≤R,S≤201≤�,�≤20。
接着输出R�行S�列字母矩阵。
【输出】
最多能走过的不同字母的个数。
【输入样例】
3 6
HFDFFB
AJHGDH
DGAGEH
【输出样例】
6
#include<iostream>
#include<cstring>
using namespace std;
int r, s, max1 = 0;
char str[30][30];
int u[4] = {1, 0, -1, 0}; // 方向数组
int v[4] = {0, -1, 0, 1};
int visit[30]; // 标记字母是否访问过
void dfs(int x, int y, int cur)
{
int xn, yn;
if (cur > max1)
{
max1 = cur;
}
for (int i = 0; i < 4; i++)
{
xn = x + u[i];
yn = y + v[i];
if (xn >= 0 && xn < r && yn >= 0 && yn < s && !visit[str[xn][yn] - 'A'])
{
visit[str[xn][yn] - 'A'] = 1;
dfs(xn, yn, cur + 1);
visit[str[xn][yn] - 'A'] = 0;
}
}
}
int main()
{
cin >> r >> s;
for (int i = 0; i < r; i++)
{
cin >> str[i];
}
memset(visit, 0, sizeof(visit));
visit[str[0][0] - 'A'] = 1;
dfs(0, 0, 1);
cout << max1 << endl;
return 0;
}
4、n皇后问题
#include <bits/stdc++.h>
using namespace std;
#define MAXN 35
int dx[4]= {1,0,-1,0};
int dy[4]= {0,-1,0,1};
char mp[MAXN][MAXN];
int qizi[MAXN][2];
int col[MAXN];
int n,k,cnt;
void dfs(int step)
{
for(int i=qizi[step-1][0]+1; i<=n-k+step; i++)
{
for(int j=1; j<=n; j++)
{
if(mp[i][j]=='#'&&col[j]==0)
{
col[j]=1;
qizi[step][0]=i;
if(step==k)
cnt++;
else
dfs(step+1);
col[j]=0;
qizi[step][0]=0;
}
}
}
return ;
}
int main()
{
int i,j;
cin>>n>>k;
while(n!=-1&&k!=-1)
{
memset(qizi,0,sizeof(qizi));
memset(col,0,sizeof(col));
cnt=0;
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
cin>>mp[i][j];
}
}
dfs(1);
cout<<cnt<<endl;
cin>>n>>k;
}
return 0;
}
5、
题目复制有点问题,题目链接:信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)
1215:迷宫
时间限制: 1000 ms 内存限制: 65536 KB
提交数:70712 通过数: 23046
【题目描述】
一天Extense在森林里探险的时候不小心走入了一个迷宫,迷宫可以看成是由n×n�×�的格点组成,每个格点只有22种状态,.
和#
,前者表示可以通行后者表示不能通行。同时当Extense处在某个格点时,他只能移动到东南西北(或者说上下左右)四个方向之一的相邻格点上,Extense想要从点A走到点B,问在不走出迷宫的情况下能不能办到。如果起点或者终点有一个不能通行(为#
),则看成无法办到。
【输入】
第1行是测试数据的组数k�,后面跟着k�组输入。每组测试数据的第11行是一个正整数n(1≤n≤100)�(1≤�≤100),表示迷宫的规模是n×n�×�的。接下来是一个n×n�×�的矩阵,矩阵中的元素为.
或者#
。再接下来一行是44个整数ha,la,hb,lbℎ�,��,ℎ�,��,描述A处在第haℎ�行, 第la��列,B处在第hbℎ�行, 第lb��列。注意到ha,la,hb,lbℎ�,��,ℎ�,��全部是从00开始计数的。
【输出】
k�行,每行输出对应一个输入。能办到则输出“YES”,否则输出“NO”。
【输入样例】
2
3
.##
..#
#..
0 0 2 2
5
.....
###.#
..#..
###..
...#.
0 0 4 0
【输出样例】
YES
NO
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
char s[105][105];
int n,ha,la,hb,lb,dir[4][2]= {{0,-1},{0,1},{-1,0},{1,0}},flag; //flag标记搜索完毕后是否能到达终点
void dfs(int ha,int la)
{
if(ha==hb&&la==lb)
{
cout<<"YES"<<endl;
flag=1;
}
if(flag) return;
for(int i=0; i<4; i++)
{
int dx=ha+dir[i][0];
int dy=la+dir[i][1];
if(dx>=0&&dx<n&&dy>=0&&dy<n&&s[dx][dy]=='.')
{
s[dx][dy]='#';//只走一次,每个方都要走一遍,只要联通,肯定能到终点
dfs(dx,dy);
}
}
}
int main()
{
int k;
cin>>k;
while(k--)
{
cin>>n;
for(int i=0; i<n; i++) for(int j=0; j<n; j++) cin>>s[i][j];
cin>>ha>>la>>hb>>lb;
if(s[ha][la]=='#'||s[hb][lb]=='#') cout<<"NO"<<endl;//提前判断始点和终点是否符合要求
else
{
flag=0;
dfs(ha,la);
}
if(flag==0) cout<<"NO"<<endl;
}
return 0;
}
6、
1218:取石子游戏
时间限制: 1000 ms 内存限制: 65536 KB
提交数:19558 通过数: 9571
【题目描述】
有两堆石子,两个人轮流去取。每次取的时候,只能从较多的那堆石子里取,并且取的数目必须是较少的那堆石子数目的整数倍,最后谁能够把一堆石子取空谁就算赢。
比如初始的时候两堆石子的数目是25和7。
25 7 | --> | 11 7 | --> | 4 7 | --> | 4 3 | --> | 1 3 | --> | 1 0 |
选手1取 | 选手2取 | 选手1取 | 选手2取 | 选手1取 |
最后选手1(先取的)获胜,在取的过程中选手2都只有唯一的一种取法。
给定初始时石子的数目,如果两个人都采取最优策略,请问先手能否获胜。
【输入】
输入包含多数数据。每组数据一行,包含两个正整数a和b,表示初始时石子的数目。
输入以两个0表示结束。
【输出】
如果先手胜,输出"win",否则输出"lose"。
【输入样例】
34 12
15 24
0 0
【输出样例】
win
lose
【提示】
假设石子数目为(a,b)且a >= b,如果[a/b] >= 2则先手必胜,如果[a/b]<2,那么先手只有唯一的一种取法。[a/b]表示a除以b取整后的值。
#include<iostream>
using namespace std;
int main()
{
int a,b;
while(cin>>a>>b)
{
if(!a&&!b)break;
int ans=0;
int t=max(a,b);
b=min(a,b);
a=t;
while(a%b)
{
if(a/b>1)break;
a-=b;
swap(a,b);
ans++;
}
if(ans%2)cout<<"lose\n";
else cout<<"win\n";
}
return 0;
}
递归写法
#include<iostream>
using namespace std;
int solve(int a,int b,int ans)
{
if(a%b==0||a/b>1)return ans;
return solve(b,a-b,ans+1);
}
int main()
{
int a,b;
while(cin>>a>>b)
{
if(!a&&!b)break;
if(solve(max(a,b),min(a,b),0)%2)cout<<"lose\n";
else cout<<"win\n";
}
return 0;
}
7、
1219:马走日
时间限制: 1000 ms 内存限制: 65536 KB
提交数:31563 通过数: 16569
【题目描述】
马在中国象棋以日字形规则移动。
请编写一段程序,给定n×m大小的棋盘,以及马的初始位置(x,y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点。
【输入】
第一行为整数T(T < 10),表示测试数据组数。
每一组测试数据包含一行,为四个整数,分别为棋盘的大小以及初始位置坐标n,m,x,y。(0≤x≤n-1,0≤y≤m-1, m < 10, n < 10)。
【输出】
每组测试数据包含一行,为一个整数,表示马能遍历棋盘的途径总数,0为无法遍历一次。
【输入样例】
1
5 4 0 0
【输出样例】
32
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int n,m,cnt,dir[8][2]= {{-1,-2},{-2,-1},{-2,1},{-1,2},{1,-2},{2,-1},{2,1},{1,2}},vis[10][10];
void dfs(int x,int y,int step)
{
if(step==n*m)
{
cnt++;
return ;
}
for(int i=0; i<8; i++)
{
int dx=x+dir[i][0];
int dy=y+dir[i][1];
if(dx>=0&&dx<n&&dy>=0&&dy<m&&!vis[dx][dy])
{
vis[dx][dy]=1;
dfs(dx,dy,step+1);
vis[dx][dy]=0;
}
}
}
int main()
{
int t,x,y;
cin>>t;
while(t--)
{
cin>>n>>m>>x>>y;
memset(vis,0,sizeof(vis));
cnt=0;
vis[x][y]=1;
dfs(x,y,1);
cout<<cnt<<endl;
}
return 0;
}
8、
1221:分成互质组
时间限制: 1000 ms 内存限制: 65536 KB
提交数:17043 通过数: 8686
【题目描述】
给定n个正整数,将它们分组,使得每组中任意两个数互质。至少要分成多少个组?
【输入】
第一行是一个正整数n。1 ≤ n ≤ 10。
第二行是n个不大于10000的正整数。
【输出】
一个正整数,即最少需要的组数。
【输入样例】
6
14 20 33 117 143 175
【输出样例】
3
#include<iostream>
#include<algorithm>
using namespace std;
int n,sum=0;
int a[20];
int visit[20];
int main()
{
cin>>n;
for(int i=0; i<n; i++)
{
cin>>a[i];
}
for(int i=0; i<n; i++)
{
if(!visit[i])
{
visit[i]=1;
sum++;
for(int j=i+1; j<n; j++)
{
if(!visit[j]&&__gcd(a[i],a[j])==1)
{
a[i]*=a[j];
visit[j]=1;
}
}
}
}
cout<<sum<<endl;
return 0;
}
9、题目链接:信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)
1222:放苹果
时间限制: 1000 ms 内存限制: 65536 KB
提交数:19387 通过数: 12617
【题目描述】
把M�个同样的苹果放在N�个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K�表示)5,1,1
和1,5,1
是同一种分法。
【输入】
第一行是测试数据的数目t�(0≤t≤200≤�≤20)。以下每行均包含二个整数M�和N�,以空格分开。1≤M,N≤101≤�,�≤10。
【输出】
对输入的每组数据M�和N�,用一行输出相应的K。
【输入样例】
1
7 3
【输出样例】
8
#include<iostream>
using namespace std;
int t,m,n,sum;
void dfs(int cur,int apple,int last)//last当前最少需放置的苹果数(保证后面的盘子苹果数>=前面盘子里的苹果数,排除掉5,1,1和1,5,1 是同一种分法情况)
{
int i;
if(cur==n&&apple==m)
{
sum++;
return;
}
else if(cur==n||apple>m)
{
return;
}
else
{
for(i=last; i<=m; i++)
{
dfs(cur+1,apple+i,i);
}
}
}
int main()
{
cin>>t;
while(t--)
{
sum=0;
cin>>m>>n;
dfs(0,0,0);
cout<<sum<<endl;
}
return 0;
}
10、寒假作业
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;
ll ans=0;
int a[20]={1,2,3,4,5,6,7,8,9,10,11,12,13};
int b[20];
bool visit[20];
void dfs(int cur,int n)
{
if(cur==13)
{
ans++;
return;
}
if(cur==3&&b[0]+b[1]!=b[2]) return;
if(cur==6&&b[3]-b[4]!=b[5]) return;
if(cur==9&&b[6]*b[7]!=b[8]) return;
if(cur==12&&b[11]!=b[9]*b[10]) return;
for(int i=0;i<n;i++)
{
if(!visit[i])
{
visit[i]=true;
b[cur]=a[i];
dfs(cur+1,n);
visit[i]=false;
}
}
}
int main()
{
dfs(0,13);
cout<<ans<<endl;
return 0;
}