几个经典算法

来源:互联网 发布:淘宝网注册支付宝流程 编辑:程序博客网 时间:2024/06/09 15:42

蛮力算法

子集

#include<iostream>using namespace std;#define MAX 1000int main() {    int n;    int a[MAX];    int tol;//子集的个数    n=4;    for(int i=0; i<n; i++) {        cin>>a[i];    }    tol=(1<<n)-1; //子集的个数    for(int i=0; i<=tol; i++) {        for(int j=0; j<n; j++)            if(i&(i<<j)) cout<<a[j];  //i<<j相当于对每一个进行标记         cout<<" "<<endl;    }}

递归算法

1.输出全排列

#include<iostream>using namespace std;void Perm(int list[],int k,int m) {    if(k==m) {        for(int i=0; i<=m; i++)            cout<<list[i]<<" ";        cout<<endl;    } else {        for(int j=k; j<=m; j++) {            swap(list[k],list[j]);            Perm(list,k+1,m);            swap(list[k],list[j]);        }    }}int main() {    int list[]= {1,2,3,4,5};    Perm(list,0,3);}

//正整数n的划分算法

#include <iostream>using namespace std;int split(int n,int m){    if(n==1||m==1) return 1;    else if (n<m) return split(n,n);    else if(n==m) return split(n,n-1)+1;    else return split(n,m-1)+split(n-m,m);}int main(){    int n;    while (cin>>n)        cout<<split(n, n)<<endl;    return 0;}    //对一个段进行递归调用    return select(j+1, right, k-j+left-1);    else return select(left, j-1, k);}int main(){    int n, k;    while (cin>>n>>k)    {        for (int i=0; i<n; i++)            cin>>a[i];        cout<<select(0, n-1, k)<<endl;    }    return 0;}

//半数集问题的递归算法

#include<iostream>            using namespace std;int a[1001];int comp(int n){    int ans=1;    if(a[n]>0)return a[n];    for(int i=1;i<=n/2;i++)         ans+=comp(i);    a[n]=ans;    return ans;}int main(){    int n;    while(cin>>n)    {        memset(a,0,sizeof(a));        a[1]=1;        cout<<comp(n)<<endl;    }    return 0;}

分治算法

选择问题
//采用分治策略找出第k小元素的算法

#include <iostream>using namespace std;#define NUM 1001int a[NUM];int select(int left, int right, int k){       //找到第k小的元素    if (left >= right) return a[left];    int i = left;    int j = right+1;     //把最左边的元素作为分界数据    int pivot = a[left];    while (true)     {        do {            i = i+1;        } while (a[i] < pivot);        do {            j = j-1;        } while (a[j] > pivot);        if (i >= j) break;        swap(a[i], a[j]);    }    if (j-left+1 == k) return pivot;    a[left] = a[j];    a[j] = pivot;    if (j-left+1 < k)        return select(j+1,right,k-j+left-1);        else return select(left,j-1,k);}    选择第K个大的数#include<iostream>using namespace std;void swap(int *a, int *b){    int tmp;    tmp = *a;    *a = *b;    *b = tmp;}int partition(int arr[], int left, int right, int pivotIndex){    int storeIndex = left;    int pivotValue = arr[pivotIndex];    int i;    swap(&arr[pivotIndex],&arr[right]);    for (i = left; i < right; i ++)    {        if (arr[i] > pivotValue)        {            swap(&arr[i],&arr[storeIndex]);            storeIndex++;        }    }    swap(&arr[storeIndex],&arr[right]);    return storeIndex;}int findKMax(int arr[], int left, int right, int k){    int nRet;    int pivotIndex = left + 1;    nRet = partition(arr,left,right,pivotIndex);    if (nRet < k)    {        return findKMax(arr,nRet+1,right,k);    }    else if (nRet > k)    {        return findKMax(arr,left,nRet-1,k);    }    return nRet;}int main(){    int i,k,nRet;    int arr[] = {8,3,4,1,9,7,6,10};    scanf("%d",&k);    nRet = findKMax(arr,0,7,k-1);    printf("The Kth Max Number locate in %d is :%d\n",nRet,arr[nRet]);    for (i = 0; i < 8; i++)    {        printf("%3d",arr[i]);    }    return 0;} 

/循环赛程表

#include <stdio.h>#define MAX 100int a[MAX][MAX];void Copy(int tox, int toy, int fromx, int fromy, int r){    for (int i=0; i<r; i++)        for (int j=0; j<r; j++)              a[tox+i][toy+j] = a[fromx+i][fromy+j];}//构造循环赛日程表,选手的数量n=2^kvoid Table(int k){       int i, r;    int n = 1 << k;     //构造正方形表格的第一行数据    for (i=0; i<n; i++)        a[0][i] = i + 1;        //采用分治算法构造整个循环日程赛表    for (r=1; r<n; r<<=1)        for (i=0; i<n; i+=2*r)        {             Copy(r, i + r, 0, i, r);            Copy(r, i, 0, i + r, r);        }}void Out(int n){     for (int i=0; i<n; i++)    {        for (int j=0; j<n; j++)             printf("%3d", a[i][j]);        printf("\n");    }    printf("\n");}int main(){     int k;    while (scanf("%d", &k) && k)    {         int n = 1 << k;         Table(k);         Out(n);    }    return 0;}

动态规划

矩阵链乘积

#include<iostream>using namespace std;int m[100][100];int p[100],s[100][100];int k;int  TraceBack(int i,int j) {        if(m[i][j]>0) return m[i][j];        if(i==j) return 0;        int u=TraceBack(i,i)+TraceBack(i+1,j)+p[i-1]*p[k]*p[j];        s[i][j]=i;        for(int k=i+1; k<j; k++) {                int t=TraceBack(i,k)+TraceBack(k+1,j)+p[i-1]*p[k]*p[j];                if(t<u) {                        u=t;                        s[i][j]=k;                }                m[i][j]=u;                return u;        }}

最多单减子序列

#include<iostream>using namespace std;#define MAX 1000int a[MAX] = {2,1,3};int select(int left,int right,int k) {    if(left>=right) return a[left];    int i =left;    int j = right+1;    int pivot = a[left]; //把第一个设为界点    while(true) {        do {            i++;        } while(a[i]<pivot);        do {            j--;        } while(a[j]>pivot);        if(i>=j) break;        swap(a[i],a[j]);    }    if(j-left+1==k) return pivot; //该界点就是要找的数    a[left]=a[j];    a[j]=pivot;    if(j-left+1<k) return select(j+1, right, k-j+left-1);    else return select(left,j-1,k);}int main() {//  int a[3] = {2,1,3};    cout<<select(0,2,2);}

//计算0-1背包的动态规划算法

#include <iostream>#include<ctime>using namespace std;#define NUM 50#define CAP 1500int v[NUM];int w[NUM];int p[NUM][CAP];//形参c是背包的容量w,n是物品的数量void knapsack(int c, int n) {     int jMax=min(w[n]-1,c);     for( int j=0; j<=jMax; j++)         p[n][j]=0;     for( int j=w[n]; j<=c; j++)         p[n][j]=v[n];    for( int i=n-1; i>1; i--)     {         jMax=min(w[i]-1,c);         for( int j=0; j<=jMax; j++)             p[i][j]=p[i+1][j];         for(int j=w[i]; j<=c; j++)             p[i][j]=max(p[i+1][j], p[i+1][j-w[i]]+v[i]);     }     p[1][c]=p[2][c];     if (c>=w[1])         p[1][c]=max(p[1][c], p[2][c-w[1]]+v[1]); } void traceback( int c, int n, int x[ ]) {     for(int i=1; i<n; i++)     {        if (p[i][c]==p[i+1][c]) x[i]=0;         else { x[i]=1; c-=w[i]; }     }    x[n]=(p[n][c])? 1:0; } int main () {    int x[NUM];    int W;    int n;    while (scanf("%d", &W) && W)     {        scanf("%d", &n);        for (int i=1; i<=n; i++)            scanf("%d%d", &w[i], &v[i]);        memset (p, 0, sizeof(p));        knapsack(W, n);        printf("%d\n", p[1][W]);        traceback(W, n, x);        for (int i=1; i<=n; i++)            if (x[i]) printf("%d ", i);        printf("\n");    }    return 0;}

//计算最大字段和的动态规划算法的最优解

#include <stdio.h>#define NUM 1001int a[NUM];int MaxSum(int n, int &besti, int &bestj){    int sum=0;     int b=0;    int begin = 0;    for (int i=1;i<=n;i++)    {        if (b>0) b+=a[i];         else {b=a[i];begin = i;}        if (b>sum)         {            sum = b;             besti = begin;             bestj = i;        }    }    return sum;}int main() {    int n;    int besti, bestj;    while (scanf("%d", &n) && n)     {        besti = 0;        bestj = 0;        for (int i=1; i<=n; i++)            scanf("%d", &a[i]);        printf("%d\n", MaxSum(n, besti, bestj));        printf("From %d to %d\n", besti, bestj);    }    return 0;}

贪心算法

//删数问题 ,找最近下降点

#include<iostream>#include<String>using namespace std;int main() {    string a;    int k;    cin>>a>>k;    if(k>=a.size()) a.erase();    else while(k>0) {        int i;        for(i=0; (i<a.size()-1)&&a[i]<=a[i+1]; i++);        a.erase(i,1);        k--;        }    while(a.size()>1 && a[0]=='0')        a.erase(0,1);    cout<<a<<endl;}

删数问题

#include<iostream>#include<string>using namespace std;int main(){   string n;   int s,i,x,l,m;   while(cin>>n>>s)   {        i=-1,m=0,x=0;        l=n.length();         while(x<s&&m==0)         {             i++;             if(n[i]>n[i+1])//出现递减,删除递减的首数字               {                  n=n.erase(i,1);                  x++;// x统计删除数字的个数                   i=-1;//从头开始查递减区间               }              if(i==l-x-2&&x<s)             m=1;//已经无递减区间,m=1脱离循环          }      cout<<n.substr(0,l-s+x)<<endl;//只打印剩下的左边l-(s-x)个数字    }    return 0;   }

回溯算法

轮船装载(回溯)

#include<iostream>using namespace std;#define NUM 100             //解空间树 int n;     //集装箱数量int c;     //轮船装在数量int w[NUM];//集装箱重量数组int x[NUM];//解向量int r;     //剩余集装箱重量int cw;    //当前轮船载重量int bestw; //当前最优载重量int bestx[NUM];//当前最优解void Backtrack(int t) {    //到达叶子节点    if(t>n) {        if(cw>bestw) {    //更新最优解            for(int i=1; i<=n; i++)                bestx[i] = x[i];            bestw = cw;        }        return;    }    //更新剩余集装箱的重量    r-= w[t];    //搜索左子树    if(cw+w[t]<=c) {        x[t]=1;        \        cw+=w[t];        Backtrack(t+1);        cw-=w[t];//恢复 状态    }    //搜索右子树    if(cw+r>bestw) {        x[t]=0;        Backtrack(t+1);    }    r+= w[t];//恢复状态}

N皇后问题

#include<iostream>#include<cmath>using namespace std;#define NUM 20int n=8;int x[NUM]; //记录解向量,列号int sum=0; //解的个数inline bool Place(int t) {    int i;    for(i=1; i<t; i++) {        if((abs(t-i) == abs(x[i]-x[t])) || (x[i]==x[t]))            return false;    }    return true;  //只要不满足循环就返回true}void Backtrack(int t) {    int i;//叶子节点    if(t>n) {        sum++;        for(i=1; i<=n; i++) {            cout<<x[i];        }        cout<<endl;    } else {        for(i=1; i<=n; i++) {            x[t]=i;            if(Place(t)) Backtrack(t+1);        }    }}int main() {    //cin>>n;    Backtrack(1);    cout<<"Total="<<sum<<endl;}

分支限界算法

装载问题分支限界算法的实现

#include<iostream>#include<queue>#include<algorithm>using namespace std;#define NUM 100int n;//集装箱的数量int c;//轮船的载重量int w[NUM];////集装箱的重量数组int MaxLoading(){    queue<int> Q;    Q.push(-1);    int i = 0;    int Ew = 0;    int bestw = 0;    int r = 0;    for(int j=1; j<n; j++)        r += w[j];    while (true)    {        int wt = Ew+w[i];        if (wt<=c)        {            if (wt>bestw) bestw = wt;            if (i<n-1) Q.push(wt);        }        if (Ew+r>bestw && i<n-1) Q.push(Ew);        Ew = Q.front();        Q.pop();        if (Ew==-1)        {            if (Q.empty()) return bestw;            Q.push(-1);            Ew = Q.front();            Q.pop();            i++;            r -= w[i];        }    }    return bestw;}int main(){    while(scanf("%d%d", &c, &n)!=EOF)    {        for(int i=0; i<n; i++)            scanf("%d",&w[i]);        int ans  =  MaxLoading();        if (ans) printf("%d\n", ans);        else printf("No answer!\n");    }    return 0;}