赞
踩
目录
此图来自AC中的Hasity作者,万分感谢;
时间复杂度为 O(n*n!);空间复杂度为 O(n);
题目描述
给定一个整数 m,将数字 1∼m 排成一排,将会有很多种排列方法。
现在,请你按照字典序将所有的排列方法输出。
输入格式
共一行,包含一个整数 m。
输出格式
按字典序输出所有排列方案,每个方案占一行。
输入样例:
3
输出样例:
1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1
- #include<iostream>
- #include<algorithm>
- #include<cstring>
-
- using namespace std;
-
- const int N = 20;
- int a[N], m;
- bool b[N];
-
- void dfs(int x)
- {
- if (x == m)
- {
- for (int i = 0; i < m; i++)
- {
- cout << a[i] << " ";
- }
- cout << endl;
- return;//回溯
- }
- for (int i = 1; i <= m; i++)
- {
- if (b[i] != true)
- {
- a[x] = i;
- b[i] = true;
- dfs(x + 1);
- b[i] = false;
- }
- }
- return;//个人感觉加上更容易理解,目的是回溯
- }
- int main()
- {
- cin >> m;
- dfs(0);
- return 0;
- }
题目描述
打印n个数中的m个数的全排列
样例输入
5 2
样例输出
1 2 1 3 1 4 1 5 2 1 2 3 2 4 2 5 3 1 3 2 3 4 3 5 4 1 4 2 4 3 4 5 5 1 5 2 5 3 5 4
- #include<iostream>
- #include<algorithm>
- #include<cstring>
-
- using namespace std;
-
- const int N = 20;
- int a[N], n, m;
- bool b[N];
-
- void dfs(int x)
- {
- if (x == m)//更换输出条件
- {
- for (int i = 0; i < m; i++)//输出m个数
- {
- cout << a[i] << " ";
- }
- cout << endl;
- return;
- }
- for (int i = 1; i <= n; i++)
- {
- if (b[i] != true)
- {
- a[x] = i;
- b[i] = true;
- dfs(x + 1);
- b[i] = false;
- }
- }
- }
- int main()
- {
- cin >> n >> m;
- dfs(0);
- return 0;
- }
-
题目描述
从 1∼n 这 n 个整数中随机选出 m 个,输出所有可能的选择方案。
输入格式
两个整数 n,m ,在同一行用空格隔开。输出格式
按照从小到大的顺序输出所有方案,每行 1 个。首先,同一行内的数升序排列,相邻两个数用一个空格隔开。
其次,对于两个不同的行,对应下标的数一一比较,字典序较小的排在前面(例如 1 3 5 7 排在 1 3 6 8 前面)。
数据范围
n>0 ;0≤m≤n ;n+(n−m)≤25输入样例:
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<algorithm>
- #include<cstring>
-
- using namespace std;
-
- const int N = 1e6 + 10;
- int n, m, a[N], b[N];
-
- void dfs(int x, int st, int p)
- {
- if (x == p)
- {
- for (int i = 0; i < p; i++)
- {
- cout << a[i]<< " ";
- }
- cout << endl;
- return;
- }
- for (int i = st; i <= n; i++)//不逆序就是字典序的核心
- {
- if (b[i] == 0)
- {
- a[x] = i;
- b[i] = 1;
- dfs(x + 1, i + 1, p);
- b[i] = 0;
- }
- }
- }
- int main()
- {
- cin >> n >> m;
- dfs(0, 1, m);
- return 0;
- }
-
题目描述
马在中国象棋以日字形规则移动。
请编写一段程序,给定 n×mn×m大小的棋盘,以及马的初始位置 (x,y)(x,y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点。
输入格式
第一行为整数 T(T<10)T(T<10),表示测试数据组数。
每一组测试数据包含一行,为四个整数,分别为棋盘的大小以及初始位置坐标 n,m,x,yn,m,x,y。(0≤x≤n−1,0≤y≤m−1,m<10,n<100≤x≤n−1,0≤y≤m−1,m<10,n<10)。输出格式
每组测试数据包含一行,为一个整数,表示马能遍历棋盘的途径总数,00 为无法遍历一次。
输入样例
输出样例
1 5 4 0 0
32
- #include<iostream>
- #include<algorithm>
- #include<cstring>
-
- using namespace std;
-
- const int N = 1e3 + 10;
- int dx[8] = { -2,-2,-1,-1,1,1,2,2 };
- int dy[8] = { -1,1,-2,2,-2,2,-1,1 };
- int n, m, a, b, t, ans, d[N][N];
-
- void dfs(int a, int b, int s)
- {
- if (s == n * m)//是否遍历完全部象棋
- {
- ans++;
- return;
- }
- for (int i = 0; i < 8; i++)
- {
- int x = a + dx[i], y = b + dy[i];
- if (x >= 0 && x < n && y >= 0 && y < m && d[x][y] == 0)
- {
- d[x][y] = 1;
- dfs(x, y, s + 1);
- d[x][y] = 0;
- }
- }
- }
-
- int main()
- {
- cin >> t;
- while (t--)
- {
- memset(d, 0, sizeof(d));
- ans = 0;
- cin >> n >> m >> a >> b;
- d[a][b] = 1;
- dfs(a, b, 1);
- cout << ans << endl;
- }
- return 0;
- }
题目描述
牛牛打 CF,已知一场比赛有 n 道题,第 i 道题的满分为 ai,时间系数为 bi,保底分为 ci,本场比赛中每次错误提交罚 p 分。即如果牛牛在第 x 分钟,这道题 y 次错误提交后通过第 i 题,他将获得 max(ci,ai−x×bi−y×p) 分。比赛持续 t 分钟,即在 t 分钟(含第 t 分钟)内做出的题目计入总分。你已经知道了他第 i 题需要花费的时间 xi 和错误提交次数 yi ,请求出牛牛可能的最大得分。输入描述
第一行三个正整数 n,t,p。(n<9。t,p<1e9)
接下来 n 行,每行 5 个正整数 a,b,c,x,y。(a,b,c,x,y<1e9)输出描述
一个正整数,表示最大的分数
样例输入
3 120 50 500 2 150 6 1 1000 4 300 12 2 1500 6 450 120 3样例输出
1266
说明
方案一:先开第 3 题,在 120 分钟时切掉,得到 1500−120×6−50×3=630。此时已无法继续切题,总分 630。 方案二:先开第 1 题,在 6 分钟时切掉,得到 438 分。再开第 2 题,在 18 分钟时切掉,得到 828 分。无法切第三题,总分 1266。 方案三:先开第 2 题,在 12 分钟时切掉,得到 852 分。再开第 1 题,在 18 分钟时切掉,得到 414 分。无法切第三题,总分 1266。 故可能的最大得分为 1266。
- #include<iostream>
- #include<algorithm>
- #include<cstring>
-
- using namespace std;
- typedef long long LL;
-
- const int N = 1e6 + 10;
- LL n, t, p, a[N], b[N], c[N], x[N], y[N], st[N];
- LL res = 0, ma = 0;
-
- void dfs(LL time)
- {
- if (time > t) return;
- ma = max(ma, res);
- for (int i = 1; i <= n; i++)
- {
- if (st[i] == 0)
- {
- st[i] = 1;
- res += max(c[i], a[i] - b[i] * (time + x[i]) - y[i] * p);;
- dfs(time + x[i]);
- res -= max(c[i], a[i] - b[i] * (time + x[i]) - y[i] * p);;
- st[i] = 0;
- }
- }
- }
- int main()
- {
- cin >> n >> t >> p;
- for (int i = 1; i <= n; i++)
- {
- cin >> a[i] >> b[i] >> c[i] >> x[i] >> y[i];
- }
- dfs(0);
- cout << ma << endl;
- return 0;
- }
题目描述
已知n个整数x1,x2,x3,...,xn,以及1个整数k( k < n)。从n个整数中任选k个整数相加,可分别得到一系列的和。列如当n = 4,k = 3,4个整数分别为3,7,12,19时,可得全部的组合与它们的和为:
3+7+12=22
3+7+19=29
7+12+19=38
3+12+19=34
现在,要求你计算出和为素数共有多少种
例如上例,只有一种的和为素数:3+7+19=29。输入
第一行两个空格隔开的整数n,k( 1 <= n <=20,k < n )。
第二行n个整数,分别为x1,x2,x3,...,xn( 1 <= xi <= 5 * 106)
输出
输出一个整数表示种类数。
样例输入
4 3 3 7 12 19样例输出
1
- #include<iostream>
- #include<cstring>
- #include<algorithm>
-
- using namespace std;
- typedef long long LL;
-
- const int N = 1e6 + 10;
- LL n, m, a[N], b[N], ans, res;
-
- int cal(int x)//判断素数
- {
- if (x < 2) return 0;
- for (int i = 2; i <= x / i; i++)
- {
- if (x % i == 0) return 0;
- }
- return 1;
- }
-
- void dfs(int x, int st, int p)
- {
- if (x == p + 1)
- {
- if (cal(res) == 1) ans++;
- return;
- }
- for (int i = st; i <= n; i++)//避免重复
- {
- if (b[i] == 0)
- {
- res += a[i];
- b[i] = 1;
- dfs(x + 1, i + 1, p);
- res -= a[i];
- b[i] = 0;
- }
- }
- return;
- }
-
- int main()
- {
- cin >> n >> m;
- for (int i = 1; i <= n; i++) cin >> a[i];
- //sort(a + 1, a + n + 1);//排不排序都行的
- dfs(1, 1, m);
- cout << ans << endl;
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。