求n个数的全排列,n不定。用c语言。用于银行家算法中求安全序列

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求n个数的全排列,n不定。用c语言。用于银行家算法中求安全序列相关的知识,希望对你有一定的参考价值。

在求安全序列中需要遍历所有的可能,从中找到一条可行的安全序列。这个遍历该怎么做??
谢谢

好久没用c了,所以代码可能要用到伪代码
先定义a[maxn]
用子函数递归
void p(int x)

if (n == x+1)

//foreach a print
//输出数组a

for (int i=1 to n)

a[x] = i;
p(x+1);
a[x] = 0;


主函数main调用p(n)
参考技术A 源代码:
#include<stdio.h>
#include<stdlib.h>
#defineN 100
#defineM 100
intavailable[M];
intmax[N][M];
intallocation[N][M];
intneed[N][M];
intn,m;

intv[N];
intflag_security=0;
/*
all_security函数为银行家算法的子算法:安全性算法
@work 系统可提供给进程继续运行的所需的各类资源数目,含m个元素
@num 进行试探性分配时,已得到资源分配的进程个数 为num-1
@s 存放已得到资源分配的进程个数,当num-1==n时即得到一个安全序列。
*/
voidall_security(int work[],int num,int s[])
int i,j;
if(num==n+1)
flag_security=1;
int j;
printf("安全序列:");
for(j=1;j<num;j++)
printf("%d ",s[j]-1);
printf("\n");

int flag_error=0;
for(i=1;i<=n;i++) //注意回溯时,同层节点的控制
flag_error=0; //之前flag_error声明在for外,导致剪枝失败
for(j=1;j<=m;j++)
if(need[i][j]>work[j])
flag_error=1;
break;


if(!v[i]&&!flag_error)
v[i]=1;
s[num]=i;
int work2[M];
for(j=1;j<=m;j++)
work2[j]=work[j];

for(j=1;j<=m;j++)
work2[j]+=allocation[i][j];

all_security(work2,++num,s);
num--;
v[i]=0;



/*
bank为银行家算法
@pid 进程的pid,范围在0 ~ n-1
@request 进程pid的资源请求向量
@return 若可分配资源给进程pid,则return 1,否则return 0
*/
intbank(int pid,int request[])
int i,j;
for(i=1;i<=m;i++)
if(request[i]>need[pid][i])
printf("error:进程%d请求的资源数量>所需的资源数量!\n",pid-1);
exit(0);

if(request[i]>available[i])
printf("error:系统无足够资源,进程%d等待中。。。\n",pid-1);
return 0;


for(i=1;i<=m;i++)
available[i]-=request[i];
allocation[pid][i]+=request[i];
need[pid][i]-=request[i];

int work[M];
for(j=1;j<=m;j++)
work[j]=available[j];

int s[N];
for(i=0;i<=n;i++)
v[i]=0;

flag_security=0;
all_security(work,1,s);
if(!flag_security)
printf("error:系统执行安全性算法,结果为此次资源分配后系统不处于安全状态!\n");
available[i]+=request[i];
allocation[pid][i]-=request[i];
need[pid][i]+=request[i];
return 0;

return 1;


intmain()
int s[10];
int i,j,pid,request[M];;
printf("输入进程数和资源种类数:\n");
scanf("%d%d",&n,&m);

printf("输入各类资源的可分配资源数向量available:\n");
for(i=1;i<=m;i++)
scanf("%d",&available[i]);

printf("输入各个进程所需最大资源数量(矩阵max:行为进程,列为资源量):\n");
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%d",&max[i][j]);


printf("输入各个进程已分配的各类资源的数量(矩阵allocation:行为进程,列为资源量):\n");
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%d",&allocation[i][j]);


printf("输入各个进程还需要各类资源的数量(矩阵need:行为进程,列为资源量):\n");
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%d",&need[i][j]);


int work[M];
printf("\n\n输出系统当前时刻的可利用资源向量:\n");
for(j=1;j<=m;j++)
work[j]=available[j];
printf("%d ",available[j]);

printf("\n");
printf("输出当前时刻n个进程的还需要资源矩阵\n");
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
printf("%d ",need[i][j]);

printf("\n");

for(j=1;j<=m;j++)
work[j]=available[j];

all_security(work,1,s);
if(flag_security)
printf("\n此刻t0处于安全状态!\n\n");
else
printf("\n此刻t0处于不安全状态,接下来可能会发生死锁!程序关闭\n\n");
return 0;


printf("请输入请求进程标志pid(0~n-1):\n");
while(~scanf("%d",&pid))
printf("请输入请求进程%d的资源请求向量:\n",pid);
for(i=1;i<=m;i++)
scanf("%d",&request[i]);

printf("输出系统当前时刻的可利用资源向量:\n");
for(j=1;j<=m;j++)
work[j]=available[j];
printf("%d ",available[j]);

printf("\n\n");
printf("输出当前时刻n个进程的还需要资源矩阵\n");
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
printf("%d",need[i][j]);

printf("\n");

int flag_request=bank(pid+1,request);
if(flag_request)
printf("进程%d请求资源成功!\n\n",pid);
else
printf("进程%d请求资源失败!\n\n",pid);

printf("请输入进程标志pid(0~n-1):\n");

return 0;

回溯算法求关于排列有关问题

八皇后问题就是一个典型的全排列问题了,这个在有一篇博客已经写过了,但是今天想在这里对于排列问题来一个总结。

排列问题主要涉及到以下几个方面:

1.不带重复数的全排列

2.带重复数的全排列

3.有限个数的全排列(例如从n个数里面选择m个数,m<n)

现在就以上几个方面把代码给大家,能理解则理解,不能理解就背下来,这种解法效率还是挺高的。

代码前提:所有的数据我都默认从0到n-1,如果在实际运用中,有可能需要进行变化。

1.不带重复数的全排列

#include<iostream>
using namespace std;
int t=0;//代表最后我算出来的结果数
int c[100];//例c[0]=2,在第0行中第一个元素在第2列(用下标莫见怪)
bool isok(int row)
{
    for(int x=0;x!=row;x++){//row代表所选的数不在同一行就可以;
        if(c[x]==c[row]){//如果他们在同一列就终止
            return false;
        }
    }
    return true;
}
void queen(int n,int row)
{
    if(row==n){
        t++;
        for(int i=0;i<n;i++){
            cout << c[i] <<  ;
        }
        cout << endl;
        return ;
    }
    else{
        for(int x=0;x!=n;x++){
            c[row]=x;
            if(isok(row)){
                queen(n,row+1);
            }
        }
    }
}
int main()
{
    int n;
    cin >> n;
    queen(n,0);
    cout << t;
    return 0;
}

 

2.带重复数的全排列

#include<iostream>
using namespace std;
int t=0;//代表最后我算出来的结果数
int c[100];//例c[0]=2,在第0行中第一个元素在第2列(用下标莫见怪)
void queen(int n,int row)
{
    if(row==n){
        t++;
        for(int i=0;i<n;i++){
            cout << c[i] <<  ;
        }
        cout << endl;
        return ;
    }
    else{
        for(int x=0;x!=n;x++){
            c[row]=x;
            queen(n,row+1);
        }
    }
}
int main()
{
    int n;
    cin >> n;
    queen(n,0);
    cout << t;
    return 0;
}

带重复数的全排列,也就是说,我不需要考虑这一列是否有元素已经放入了,我想放就放

3.有限个数的全排列(例如从n个数里面选择m个数,m<n)

#include<iostream>
using namespace std;
int t=0;
int c[100];
bool isok(int row)
{
    for(int x=0;x!=row;x++){//row代表所选的数不在同一行就可以;
        if(c[x]==c[row]){//如果他们在同一列就终止
            return false;
        }
    }
    return true;
}
void queen(int n,int m,int row)
{
    if(row==m){
        t++;
        for(int i=0;i<m;i++){
            cout << c[i] <<  ;
        }
        cout << endl;
        return ;
    }
    else{
        for(int x=0;x!=n;x++){
            c[row]=x;
            if(isok(row)){
                queen(n,m,row+1);
            }
        }
    }
}
int main()
{
    int n,m;//从n个数选择m个数
    cin >> n >> m;
    queen(n,m,0);
    cout << t;
    return 0;
}

 

以上是关于求n个数的全排列,n不定。用c语言。用于银行家算法中求安全序列的主要内容,如果未能解决你的问题,请参考以下文章

回溯算法求关于排列有关问题

c语言全排列

算法提高 排列数 (全排列)

蓝桥 :算法提高 排列数(深度优先)

算法提高 排列数

算法学习——递归和排列组合