全排列问题(form.cpp)
【问题描述】
输出自然数1 到n 所有不重复的排列,即n 的全排列,要求所产生的任一数字序列中不允许出现重复的
数字。
【输入形式】
n(1≤n≤9)
【输出形式】
由1~n 组成的所有不重复的数字序列,每行一个序列。
【样例输入】
3
【样例输出】
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue>
# include<map>
# include<string>
# include<cstring>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII;
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846;
int a[10],n;
int vis[10];
void dfs(int u){
if(u == n + 1){
for(int j = 0 ; j < n ; j ++ )
cout<<a[j]<<" ";
cout<<"\n";
return ;
}
for(int i = 1 ; i <= n ; i ++ ){
if(!vis[i]){}
vis[i] = 1;
a[u] = i;
dfs(u+1);
vis[i] = 0;
}
}
}
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
dfs(1);
return 0;
}
组合的输出
【问题描述】
排列与组合是常用的数学方法,其中组合就是从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
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue>
# include<map>
# include<string>
# include<cstring>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII;
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846;
int a[10],n,m;
int vis[10];
void dfs(int u,int s){
if(s == m + 1){
for(int j = 1 ; j <= m ; j ++ )
cout<<a[j]<<" ";
cout<<"\n";
return ;
}
for(int i = u ; i <= n ; i ++ ){
if(i>a[s-1]){
a[u] = i;
dfs(u+1,s+1);
}
}
}
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
dfs(1,1);
return 0;
}
N 皇后问题(queen)
【问题描述】
在N*N 的棋盘上放置N 个皇后(n<=10)而彼此不受攻击(即在棋盘的任一行,任一列和任一对角线上
不能放置2 个皇后),编程求解所有的摆放方法。
【输入形式】
输入:n
【输出形式】
每行输出一种方案,每种方案顺序输出皇后所在的列号,各个数之间有空格隔开。若无方案,则输出
no solute!
【样例输入】
4
【样例输出】
2 4 1 3
3 1 4 2
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue>
# include<map>
# include<string>
# include<cstring>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII;
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846;
int col[15],arg[15],unarg[15],vis[15][15];
int a[15],n,flag;
void dfs(int i){
if(i == n+1){
flag = 1;
for(int i = 1 ; i <= n ; i ++){
cout<<a[i]<<" ";
}
cout<<"\n";
return ;
}
for(int j = 1 ; j <= n ;j ++ ){
if(!col[j] && !arg[n + i - j] && !unarg[i+j] ){
col[j] = arg[n + i - j] = unarg[i+j] = 1;
a[i] = j;
dfs(i+1);
col[j] = arg[n + i - j] = unarg[i+j] = 0;
}
}
}
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
dfs(1);
if(flag == 0) cout<<"no solute!";
return 0;
}
有重复元素的排列问题(perm)
【问题描述】
设R={ r1, r2 , …, rn}是要进行排列的n个元素。其中元素r1, r2 , …, rn可能相同。试设计一个算法,
列出R的所有不同排列。
给定n 以及待排列的n 个元素。计算出这n 个元素的所有不同排列。
【输入形式】
输入数据:
文件的第1 行是元素个数n,1≤n≤500。接下来的1 行是待排列的n个元素。
【输出形式】
计算出的n个元素的所有不同排列输出。文件最后1行中的数是排列总数。
【样例输入】
4
aacc
【样例输出】
aacc
acac
acca
caac
caca
ccaa
6
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue>
# include<map>
# include<string>
# include<cstring>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII;
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846;
int n,sum;
int vis[10];
char s[505];
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> s;
sort(s,s+n);
do{
cout<<s<<"\n";
sum++;
}while(next_permutation(s,s+n));
cout<<sum;
return 0;
}
子集和问题(subsum)
【问题描述】
子集和问题的一个实例为〈S,t〉。其中,S={ x1, x2,…, xn}是一个正整数的集合,c是一个正整
数。子集和问题判定是否存在S的一个子集S1,使得子集S1和等于c。
对于给定的正整数的集合S={ x1, x2,…, xn}和正整数c,编程计算S 的一个子集S1,使得子集S1和等于c。
【输入形式】
输入共两行,第一行有2个正整数n和c,n表示S的个数,c是子集和的目标值。接下来一行中,有n个正整数,表示集合S中的元素。
【输出形式】
输出子集和问题的解;当问题和无解时,输出"No Solution!"。
【样例输入】
5 10
2 2 6 5 4
【样例输出】
2 2 6
【样例说明】
1、n<10000、c<10000000
2、如果有解,只需要输出“最靠前”的一个解
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue>
# include<map>
# include<string>
# include<cstring>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII;
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846;
int n , m, a[MAX],ans,flag,sum;
bool vis[MAX];
void print(int i) {
for (int j = 0; j <= i; j++) {
if (vis[j] == true) {
if (j != i) cout<<a[j]<<" ";
else cout<<a[j];
}
}
}
void dfs(int u){
if (u >= n || flag) return;
vis[u] = true;
ans += a[u];
if (ans == m) {
print(u);
flag = 1;
}
else if (ans < m) {
dfs(u + 1);
}
vis[u] = false;
ans -= a[u];
dfs(u + 1);
return;
}
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
for(int i = 0 ; i < n ; i ++ ) cin >> a[i],sum+=a[i];
if(sum < m){
cout<<"No Solution!";
return 0;
}
if(sum == m){
for(int i = 0 ;i < n ; i++ )
cout<<a[i]<<" ";
return 0;
}
dfs(0);
if(flag == 0 )cout<<"No Solution!";
return 0;
}
工作分配问题(job)
【问题描述】
设有n件工作分配给n个人。将工作i分配给第j个人所需的费用为cij。试设计一个算法,为每一个人都分配一件不同的工作,并使总费用达到最小。
设计一个算法,对于给定的工作费用,计算最佳工作分配方案,使总费用达到最小。
【输入形式】
输入共两行,第一行有一个正整数n(1<=n<=20)。接下来的n行,每行n个数,第i行表示第i个人各项工作费用。
【输出形式】
输出最小总费用
【样例输入】
3
4 2 5
2 3 6
3 4 5
【样例输出】
9
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue>
# include<map>
# include<string>
# include<cstring>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII;
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846;
int n, a[25][25];
bool vis[25];
int ans;
void dfs(int u,int sum){
if(u == n){
ans = min(ans,sum);
return ;
}
if(sum > ans) return ;
for(int i = 0 ; i < n ; i++ ){
if(!vis[i]){
vis[i] = true;
dfs(u+1,sum+a[u][i]);
vis[i] = false ;
}
}
}
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
for(int i = 0 ; i < n ; i ++ )
for(int j = 0 ; j < n ; j ++ )
cin >> a[i][j] , ans+=a[i][j];
dfs(0,0);
cout<<ans;
return 0;
}
装载问题(load)
【问题描述】
有一批共n个集装箱要装上艘载重量为c的轮船,其中集装箱i的重量为wi。找出一种最优装载方案,将轮船尽可能转满,即在装载体积不受限制的情况下,将尽可能重的集装箱装上轮船。
【输入形式】
输入共2行,第一行有2个正整数n和c。n是集装箱数,c是轮船的载重量。接下来的1行中有n个正整数,表示集装箱的重量。
【输出形式】
输出最大装载重量
【样例输入】
5 10
7 2 6 5 4
【样例输出】
10
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue>
# include<map>
# include<string>
# include<cstring>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII;
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846;
int dp[MAX],n,m;
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
for(int i = 0 ; i < n ; i ++ ) {
int v;
cin >> v;
for(int j = m ; j >= v ; j -- )
dp[j] = max(dp[j],dp[j-v] + v);
}
cout<<dp[m];
return 0;
}
字符序列(characts)
【问题描述】
从三个元素的集合[A,B,C]中选取元素生成一个N个字符组成的序列,使得没有两个相邻字的子序列相同。例:N = 5时ABCBA是合格的,而序列ABCBC与ABABC是不合格的,因为其中子序列BC,AB是相同的。
【输入形式】
输入仅有一个整数n(1<=n<=15)。
【输出形式】
输出满足条件的N个字符的序列总数。
【样例输入】
4
【样例输出】
18
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue>
# include<map>
# include<string>
# include<cstring>
`using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII;
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846;
int n, ans, a[MAX];
void dfs(int u)
{
if(u > n ){
ans++;
return ;
}
for(int i = 1; i <= 3; i ++)
{
if(i == a[u - 2] && a[u - 1] == a[u - 3]) continue;
a[u] = i;
dfs(u+1);
}
}
int main()
{
cin>>n;
dfs(1);
cout<<ans;
return 0;
}
试卷批分(grade)
【问题描述】
某学校进行了一次英语考试,共有10道是非题,每题为10分,解答用1表示“是”,用0表示“非”的方式。但老师批完卷后,发现漏批了一张试卷,而且标准答案也丢失了,手头只剩下了3张标有分数的试卷。
请编一程序依据这三张试卷,算出漏批的那张试卷的分数。
【输入形式】
【输出形式】
【样例输入】
0 0 1 0 1 0 0 1 0 0
【样例输出】
70
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue>
# include<map>
# include<string>
# include<cstring>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII;
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846;
int n;
int vis[10];
int s[5];
int a[5][11]={
{0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,1,0,1,0,0,1,0,0},
{0,0,1,1,1,0,1,0,1,1,1},
{0,0,1,1,1,0,0,0,1,0,1},
{0,0,0,1,1,1,0,0,1,1,1}
};
void dfs(int x){
for(int i=0;i<=1;i++)
{
for(int j=1;j<=4;j++)
if(a[j][x]==i)
s[j]+=10;
if(x==10)
{
if(s[1]==70 && s[2]==50 && s[3]==30)
{
cout<<s[4]<<endl;
return;
}
}
else dfs(x+1);
for(int j=1;j<=4;j++)
if(a[j][x]==i)
s[j] -= 10;
}
}
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
for(int i = 0 ; i < 10 ; i++ ) cin >> n;
dfs(0);
return 0;
}
迷宫问题(migong)
【问题描述】
设有一个 N*N(2<=N<10)方格的迷宫,入口和出口分别在左上角和右上角。迷宫格子中
分别放0 和1,0 表示可通,1 表示不能,入口和出口处肯定是0。迷宫走的规则如下所示:
即从某点开始,有八个方向可走,前进方格中数字为0 时表示可通过,为1 时表示不可通过,
要另找路径。找出所有从入口(左上角)到出口(右上角)的路径(不能重复),输出路径总
数,如果无法到达,则输出0。
【输入形式】
第一行为方阵N
接下来的N行为方阵值。
【输出形式】
路径总数.
【样例输入】
3
0 0 0
0 1 1
1 0 0
【样例输出】
2
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue>
# include<map>
# include<string>
# include<cstring>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII;
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846;
int n,m,ans;
int a[25][25];
bool vis[25][25];
int dx[8]={-1,0,1,0,1,1,-1,-1};
int dy[8]={0,1,0,-1,1,-1,1,-1};
void dfs(int x, int y){
if(x == 1 && y == n){
ans++;
return ;
}
for(int i = 0 ; i < 8 ; i++ ){
int xx = x + dx[i];
int yy = y + dy[i];
if(xx >= 1 && xx <= n && yy >= 1&& yy <= n && !vis[xx][yy] && !a[xx][yy])
{
vis[xx][yy] = true;
dfs(xx,yy);
vis[xx][yy] = false;
}
}
}
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n ;
for(int i = 1 ; i <= n ;i ++ )
for(int j = 1 ; j <= n ; j ++ )
cin >> a[i][j];
vis[1][1] = true;
dfs(1,1);
cout<<ans;
return 0;
}
部落卫队
【问题描述】
原始部落byteland中的居民们为了争夺有限的资源,经常发生冲突。几乎每个居民都有他的仇敌。部落酋长为了组织一支保卫部落的队伍,希望从部落的居民中选出最多的居民入伍,并保证队伍中任何2个人都不是仇敌。
编程任务:
给定byteland部落中居民间的仇敌关系,编程计算组成部落卫队的最佳方案。
【输入形式】
第一行有2个正整数n和m,表示byteland部落中有n个居民,居民间有m个仇敌关系。居民编号1,2,3…,n。接下来的m行中,每行有2个正整数u和v,表示居民u与居民v是仇敌。
【输出形式】
第一行是部落卫队的总人数;第二行是卫队组成xi,1<=i<=n<=100,xi=0表示居民i不在卫队中,xi=1表示居民i在卫队中。如果有多种方案,输出字典序大的。
【样例输入】
7 10
1 2
1 4
2 4
2 3
2 5
2 6
3 5
3 6
4 5
5 6
【样例输出】
3
1 0 1 0 0 0 1
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue>
# include<map>
# include<string>
# include<cstring>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII;
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846;
int a[MAX],n,m,x[MAX],ans,mp[105][105],sum;
void dfs(int u,int sum){
if(u > n ){
if(sum <= ans) return;
ans = sum;
for(int i = 1; i <= n ; i ++ )
a[i] = x[i];
return ;
}
int flag = 1;
for(int j = 1 ; j < u ; j ++ ){
if(mp[j][u] && x[j]) {
flag = 0 ;
break;
}
}
if(flag){
x[u] = 1;
dfs(u+1,sum+1);
x[u] = 0;
}
dfs(u+1,sum);
}
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
for(int i = 1; i <= m ; i ++ ){
int u ,v;
cin >> u >> v;
mp[u][v] = mp[v][u] = 1;
}
dfs(1,0);
cout<<ans<<"\n";
for(int i = 1 ; i <= n ; i ++ )
cout<<a[i]<<" ";
return 0;
}
最佳调度问题
【问题描述】
假设有n个任务由k个可并行工作的机器完成。完成任务i需要的时间为ti.试设计一个算法找出完成这n个任务的最佳调度,使得完成全部任务的时间最早。
编程任务:
对任意给定的整数n和k ,以及完成任务i需要的时间为ti,i=1~n。编程计算完成这n个任务的最佳调度。
【输入形式】
第一行有2个正整数n和k;第2行的n个正整数是完成n个任务需要的时间。(1≤n≤20,1≤k≤6)
【输出形式】
输出完成全部任务的最早时间ti(1≤ti≤100)。
【样例输入】
7 3
2 14 4 16 6 5 3
【样例输出】
17
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue>
# include<map>
# include<string>
# include<cstring>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII;
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846;
int n , k ,a[MAX] , ans,num[MAX],tot;
void dfs(int x){
if(x > n){
int res = num[1];
for(int i = 2; i <= k ; i++ )
res = max(res,num[i]);
ans = min(ans,res);
return ;
}
else{
for(int i = 1 ; i <= tot - 1 ; i ++ ){
if(num[i] + a[x] <= ans){
num[i] += a[x];
dfs(x+1);
num[i] -= a[x];
}
}
if(tot <= k){
num[tot++] += a[x];
dfs(x+1);
num[--tot] -= a[x];
}
}
}
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> k;
for(int i = 1 ; i <= n ; i ++ ) cin >> a[i],ans+=a[i];
sort(a + 1,a + 1 + n);
num[1] += a[1];
tot = 2;
dfs(2);
cout<<ans;
return 0;
}
图的m着色问题
【问题描述】
给定无向连通图G和m种不同的颜色。用这些颜色为图G的各顶点着色,每个顶点着一种颜色。如果有一种着色法使G中每条边的2个顶点着不同颜色,则称这个图是m可着色的。图的m着色问题是对于给定图G和m种颜色,找出所有不同的着色法。
编程任务:
对于给定的无向连通图G和m种不同的颜色,编程计算图的所有不同的着色法。
【输入形式】
第1行有3个正整数n,k和m,表示给定的图G有n个顶点和k条边,m种颜色。顶点编号为1,2,…,n。接下来k行中,每行有2个正整数u,v,表示图G的一条边(u,v)。(n<=100)
【输出形式】
输出计算出的不同的着色方案数。
【样例输入】
5 8 4
1 2
1 3
1 4
2 3
2 4
2 5
3 4
4 5
【样例输出】
48
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue>
# include<map>
# include<string>
# include<cstring>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII;
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846;
int n,m,k,ans;
int colour[105];
int mp[105][105];
bool check(int x){
for(int i = 1 ; i <= n ; i ++ ){
if(mp[x][i] && mp[i][x] && colour[x] == colour[i]) return false;
}
return true;
}
void dfs(int u){
if(u > n){
ans++;
return ;
}
for(int i = 1 ; i <= m ; i ++ ){
colour[u] = i;
if(check(u)){
dfs(u + 1);
}
colour[u] = 0;
}
}
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> k >> m;
for(int i = 1 ; i <= k ; i ++ ){
int u , v;
cin >> u >> v;
mp[u][v] = mp[v][u] = 1;
}
dfs(1);
cout<<ans;
return 0;
}
自然数的拆分问题
【问题描述】
任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和。
【输入形式】
输入一个自然数n.
【输出形式】
输出不同的拆分方法,每一种拆分方法输出到一行。
【样例输入】
7
【样例输出】
1+1+1+1+1+1+1
1+1+1+1+1+2
1+1+1+1+3
1+1+1+2+2
1+1+1+4
1+1+2+3
1+1+5
1+2+2+2
1+2+4
1+3+3
1+6
2+2+3
2+5
3+4
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue>
# include<map>
# include<string>
# include<cstring>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII;
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846;
int n, a[25];
bool vis[25];
int ans;
void dfs(int ans,int j,int now){
if(ans==n) {
for(int i=1;i<=j-1;i++)
if(i==1) cout<<a[i];
else cout<<"+"<<a[i];
cout<<"\n";
return ;
}
if(ans>n) return ;
for(int i=now;i<=n-1;i++){
a[j]=i;
dfs(ans+i,j+1,i);
a[j]=0;
}
}
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
dfs(0,1,1);
return 0;
}
整数的划分(Noip2001)
【问题描述】
将整数nn分成kk份,且每份不能为空,任意两份不能相同(不考虑顺序)。
例如:n=7n=7,k=3k=3,下面三种分法被认为是相同的。
{1,1,5};{1,5,1};{5,1,1}{1,1,5};{1,5,1};{5,1,1};
问有多少种不同的分法。 输出一个整数,即不同的分法。
【输入形式】
两个整数nn,k(6<n≤200,2≤k≤6)k(6<n≤200,2≤k≤6),中间用单个空格隔开。
【输出形式】
一个整数,即不同的分法。
【样例输入】
7 3
【样例输出】
4
【样例说明】
四种分法为:{1,1,5};{1,2,4};{1,3,3};{2,2,3}{1,1,5};{1,2,4};{1,3,3};{2,2,3}。
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue>
# include<map>
# include<string>
# include<cstring>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII;
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846;
int ans,n,m;
void dfs(int pos,int sum,int cnt){
if(cnt == m){
if(sum == n) ans++;
return ;
}
if(sum > n ) return ;
for(int i = pos ; i <= n ; i ++ ){
if(sum + (m - cnt) * i <= n )
dfs(i,sum + i , cnt + 1);
}
}
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
dfs(1,0,0);
cout<<ans;
return 0;
}