暴力求解法

有错还请指正

简单枚举

例题7-1 除法(Division, UVa 725)

输入正整数n,按从小到大的顺序输出所有形如abcde/fghij = n的表达式,其中a~j恰好 为数字0~9的一个排列(可以有前导0),2≤n≤79。

样例输入:

62

样例输出:

79546 / 01283 = 62

94736 / 01528 = 62

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include<stdio.h>
#include<string.h>
int main()
{
int i,j,n,s1,s2,flag[10];
while(~scanf("%d",&n))
{
for(i=1234;i<50000;i++)
{
memset(flag,0,sizeof(flag));
s1=i;
s2=i*n;
while(s1||s2)
{
if(!flag[s1%10])
{
flag[s1%10]=1;
s1/=10;
}
else
break;
if(!flag[s2%10])
{
flag[s2%10]=1;
s2/=10;
}
else
break;
}
for(j=0;j<10;j++)
if(!flag[j])
break;
if(j==10&&i*n<=98765)
{
if(i<10000)
printf("%d / 0%d = %d\n",i*n,i,n);
else
printf("%d / %d = %d\n",i*n,i,n);
}
}
}
return 0;
}

例题7-2 最大乘积(Maximum Product, UVa 11059)

输入n个元素组成的序列S,你需要找出一个乘积最大的连续子序列。如果这个最大的乘 积不是正数,应输出0(表示无解)。1≤n≤18,-10≤Si≤10。

样例输入:

3

2 4 -3

5

2 5 -1 2 -1

样例输出:

8 20

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<stdio.h>
long long max=-1e19;
int main()
{
int t;
scanf("%lld",&t);
while(t--){
long long int n,a[20]={0},ret=1;
scanf("%lld",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
for(int i=1;i<=n-1;i++){
for(int j=i+1;j<=n;j++){
ret=1;
for(int k=i;k<=j;k++){
ret=ret*a[k];
}
if(ret>max)
max=ret;
}
}
if(max<0)
printf("0\n");
else
printf("%lld\n",max);
}
return 0;
}

例题7-3 分数拆分(Fractions Again?!, UVa 10976)

输入正整数k,找到所有的正整数x>=y,使得1/k=1/x + 1/y;

样例输入:

2

12

样例输出:

2

1/2 = 1/6 + 1/3;

1/2 = 1/4 + 1/4;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
int main()
{
int k;
while(~scanf("%d",&k)){
for(int y=k+1;y<=2*k;y++){
if(k*y%(y-k)==0){
int x = k*y/(y-k);
printf("1/%d = 1/%d + 1/%d\n",k,x,y);
}
}
}
return 0;
}

从1/12=1/156+1/13可以看出,x可以比y大很多。由于x>=y,有1/x<=1/y,因此1/k-1/y<=1/y,即y<=2 * k.这样,只需要在2 * k范围之内枚举y,然后根据y尝试计算出x即可

枚举排列

7.2.1 生成1~n的排列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<stdio.h>
int a[1000];
void print_permutation(int n,int *A,int cur){
if(cur==n){
for(int i=0;i<n;i++)
printf("%d ",A[i]);
printf("\n");
}
else
for(int i=1;i<=n;i++){
int ok=1;
for(int j=0;j<cur;j++)
if(A[j]==i)
ok=0;
if(ok){
A[cur]=i;
print_permutation(n,A,cur+1);
}
}
}
int main()
{
int n,cur=0;
scanf("%d",&n);
print_permutation(n,a,0);
return 0;
}

当然我知道c++STL里有next_permutation函数,这里是函数的一种实现方式(递归)

1
2
3
4
5
6
7
8
9
void next_pre(int n,int x){
do
{
for(int i=0;i<n;i++){
printf("%d",p[i]);
}
printf("\n");
}while(next_permutation(p,p+n));
}

7.2.2 生成可重集的排列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include<cstdio>
#include<algorithm>
using namespace std;
int ans[30],a[30];
void print_permutation(int n,int*x,int pos){
if (pos==n) {
for (int i=0;i<n;i++)
printf("%d ",x[i]);
printf("\n");
}
else for (int i=0;i<n;i++){
if (!i||(a[i]!=a[i-1])){
int c1=0,c2=0;
for (int j=0;j<pos;j++)
if (x[j]==a[i]) c1++;
for (int j=0;j<n;j++)
if (a[i]==a[j]) c2++;
if (c1<c2) {
x[pos]=a[i];
print_permutation(n,x,pos+1);
}
}
}
}
int main(){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
sort(a,a+n);
print_permutation(n,ans,0);
return 0;
}

7.2.4 下一个排列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<cstdio>
#include<algorithm>
using namespace std;
int main(){
int n,p[10];
scanf("%d",&n);
for(int i = 0; i < n; i++)
scanf("%d", &p[i]);
sort(p, p+n);
do {
for(int i = 0; i < n; i++)
printf("%d ", p[i]);
printf("\n");
}while(next_permutation(p, p+n));
return 0;
}

待更新。。。