文章標題

/*
杭電題目第10頁:http://acm.hdu.edu.cn/listproblem.php?vol=10 最下面的中文題
杭電題目第11頁:http://acm.hdu.edu.cn/listproblem.php?vol=11 除2089外的所有的中文題
*/

//排序
#include <stdio.h>
//冒泡
void sort_bubble(int* a, int n)
{
    int i, j, t;
    for (i=0; i<n-1; i++){
        for (j=0; j<n-1; j++){
            if (a[j] > a[j+1]){
                t = a[j];
                a[j] = a[j+1];
                a[j+1] = t;
            }
        }
    }
}
//選擇
void sort_select(int* a, int n)
{
    int i, j, t;
    int k;
    for (i=0; i<n; i++){
        k=i;
        for (j=i+1; j<n; j++){
            if (a[j] < a[k]) k = j;
        }
        t = a[k];
        a[k] = a[i];
        a[i] = t;
    }
}
//快速排序
void qp(int* a, int n, int l, int r)
{
    int i, j, k, t;
    i = l;
    j = r;
    k = a[(i+j) >> 1];
    while (i <= j){
        while (a[i] < k) i++;
        while (a[j] > k) j--;
        if (i <= j){
            t = a[i];
            a[i] = a[j];
            a[j] = t;
            i++;
            j--;
        }
    }
    if (i < r) qp(a, n, i, r);
    if (l < j) qp(a, n, l, j);
}
//歸併排序
int r[100];
void msort(int* a, int n, int s, int t)
{
    int m, i, j, k;

    if (s == t) return;
    m = (s + t) >> 1;
    msort(a, n, s, m);
    msort(a, n, m+1, t);
    i = s; j = m+1; k = s;
    while (i<=m && j<=t){
        if (a[i] < a[j]){
            r[k] = a[i];
            i++;
            k++;
        }else{
            r[k] = a[j];
            j++;
            k++;
        }
    }
    while (i <= m){
        r[k] = a[i];
        i++;
        k++;
    }
    while (j <= t){
        r[k] = a[j];
        j++;
        k++;
    }
    for (i=s; i<=t; i++) a[i] = r[i];
}

int main()
{
    int a[100] = {0};
    int n;
    int i;

    scanf("%D", &n);
    for (i=0; i<n; i++) scanf("%d", &a[i]);
    sort_bubble(a, n);
    for (i=0; i<n; i++) printf("%d ", a[i]);

    return 0;
}

//KMP(改進的字符串匹配算法)
#include<stdio.h>
#include<string.h>

char T[10000];
char P[200];
int f[210];

void getFail(char *P, int *f)
{
    int m = strlen(P);

    f[0] = f[1] = 0;
    for (int i=1; i<m; i++)
    {
        int j = f[i];
        while (j && P[i] != P[j]) j = f[j];
        f[i+1] = P[i] == P[j] ? j+1 : 0;
    }
}

int Find(char *T, char *P, int *f)
{
    int n = strlen(T), m = strlen(P);

    getFail(P, f);
    int j = 0;
    for (int i=0; i<n; i++)
    {
        while (j && T[i] != P[j]) j = f[j];
        if (T[i] == P[j]) j++;
        if (j == m)
            return i-m+1;  //找到字符串,返回字符串的起始位置
    }

    return -1;  //沒有找到,返回-1
}

int main()
{
    scanf("%s", T); //在T裏面找P
    scanf("%s", P);

    printf("%s在%s中第一次出現的位置是:%d\n", P, T, Find(T, P, f));

    return 0;
}
桶排序
#include <stdio.h>

int cnt[10000];

int main()
{
    int n;
    int i, j;
    int x;

    printf("請輸入數據個數:");
    scanf("%d", &n);
    printf("請輸入數據:");
    for (i=0; i<n; i++){
        scanf("%d", &x);
        cnt[x]++;
    }

    printf("排序後的數據如下:");
    for (i=0; i<10000; i++){
        for (j=0; j<cnt[i]; j++) printf("%d ", i);
    }
    printf("\n");

    return 0;
}
堆排序
#include<stdio.h>

int a[10000];
int n,tot;

int down(int i)
{
    int j,t,tmp;

    tmp=tot>>1;
    while (i<=tmp)
    {
        j=2*i;
        if ((j<tot)&&(a[j+1]<a[j])) j++;
        if (a[i]>a[j])
        {
            t=a[i]; a[i]=a[j]; a[j]=t;
            i=j;
        }
        else break;
    }
}

int main()
{
    int i,t,tmp;

    scanf("%d",&n);
    for (i=1;i<=n;i++) scanf("%d",&a[i]);

    tot=n;
    tmp=n>>1;
    for (i=tot;i>=1;i--) down(i);
    for (i=1;i<=n;i++)
    {
        t=a[1]; a[1]=a[tot]; a[tot]=t;
        tot--;
        down(1);
    }
    for (i=n;i>1;i--) printf("%d ",a[i]); printf("%d",a[i]);

    return 0;
}

基數排序:https://www.cnblogs.com/Braveliu/archive/2013/01/21/2870201.html
#include <stdio.h>

int maxbit(int data[], int n) //輔助函數,求數據的最大位數
{
    int d = 1; //保存最大的位數
    int p = 10;
    for(int i = 0; i < n; ++i)
    {
        while(data[i] >= p)
        {
            p *= 10;
            ++d;
        }
    }
    return d;
}

void radixsort(int data[], int n) //基數排序
{
    int d = maxbit(data, n);
    int tmp[1000];
    int count[10]; //計數器
    int i, j, k;
    int radix = 1;
    for(i = 1; i <= d; i++) //進行d次排序
    {
        for(j = 0; j < 10; j++)
            count[j] = 0; //每次分配前清空計數器
        for(j = 0; j < n; j++)
        {
            k = (data[j] / radix) % 10; //統計每個桶中的記錄數
            count[k]++;
        }
        for(j = 1; j < 10; j++)
            count[j] = count[j - 1] + count[j]; //將tmp中的位置依次分配給每個桶
        for(j = n - 1; j >= 0; j--) //將所有桶中記錄依次收集到tmp中
        {
            k = (data[j] / radix) % 10;
            tmp[count[k] - 1] = data[j];
            count[k]--;
        }
        for(j = 0; j < n; j++) //將臨時數組的內容複製到data中
            data[j] = tmp[j];
        radix = radix * 10;
    }
}

int main()
{
    int a[100];
    int n;
    int i;

    scanf("%d",&n);
    for (int i=0; i<n; i++) scanf("%d", &a[i]);
    radixsort(a, n);
    for (i=0; i<n; i++) printf("%d ", a[i]);

    return 0;
}


//n皇后問題
// N皇后問題是一個經典的問題,在一個N*N的棋盤上放置N個皇后,每行一個並使其不能互相攻擊(同一行、同一列、同一斜線上的皇后都會自動攻擊)

/*在n*n的棋盤中放置n個皇后,要求所有的皇后都不在同一行、同一列、同一對角線*/
#include <stdio.h>

int n;
int cnt;
int r[11];
short low[11], left[22], right[22];

void dfs(int deep)
{
    int i;
    if (deep > n){
        cnt++;
        printf("方案%d:\n", cnt);
        for (i=1; i<=n; i++) printf("第%d行放在第%d列\n", i, r[i]);
        return;
    }
    for (i=0; i<n; i++){
        if (!low[i] && !left[deep+i] && !right[deep-i+10]){
            low[i] = left[deep+i] = right[deep-i+10] = 1;
            r[deep] = i;
            dfs(deep+1);
            low[i] = left[deep+i] = right[deep-i+10] = 0;
            r[deep] = 0;
        }
    }
}

int main()
{
    printf("請輸入皇后的數量:");
    scanf("%d", &n);
    dfs(1);

    return 0;
}

//自然數分解
/*輸入一個自然數,把它分解成若干個自然數的和,輸出所有方案*/
#include <stdio.h>

int n;
int a[100];

void dfs(int deep, int start, int last)
{
    int i;
    if (last == 0){
        printf("%d=", n);
        for (i=0; i<deep-1; i++) printf("%d+", a[i]);
        printf("%d\n", a[deep-1]);
        return;
    }
    for (i=start; i<=last; i++){
        a[deep] = i;
        dfs(deep+1, i, last-i);
        a[deep] = 0;
    }
}

int main()
{
    printf("請輸入要分解的自然數:");
    scanf("%d", &n);
    dfs(0, 1, n);

    return 0;
}
//斐波那契——矩陣乘法
//跳臺階,實質:斐波那契數列
/*跳臺階:一隻青蛙一次可以跳上1級臺階,也可以跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法。
設f[i]爲到達第i級臺階的方案數,那麼
f[0]=1(在地面上),
f[1]=1,
f[2]=2(直接從地面跳到第二級或者先到第一級再到第二級),
f[3]=f[2]+f[1],
f[4]=f[3]+f[2],
……
f[i]=f[i-1]+f[i-2]
斐波那契數列*/
#include<stdio.h>

int f[3][3],a[3][3],b[3][3],c[3][3];
int n;
const  int MO=15746;

void ksm(int t)
{
    int i,j,k;

    a[1][1]=1; a[1][2]=1;
    a[2][1]=1; a[2][2]=0;
    f[1][1]=1; f[1][2]=1;
    f[2][1]=1; f[2][2]=0;
    while (t>0)
    {
        if (t%2==1)
        {
            for (i=1;i<=2;i++)
                for (j=1;j<=2;j++)
                   for (k=1;k<=2;k++)
                      c[i][j]=(c[i][j]+f[i][k]*a[k][j])%MO;
            for (i=1;i<=2;i++)
                for (j=1;j<=2;j++)
            {
                f[i][j]=c[i][j];
                c[i][j]=0;
            }
        }
        t=t>>1;
        for (i=1;i<=2;i++)
            for (j=1;j<=2;j++)
               for (k=1;k<=2;k++) c[i][j]=(c[i][j]+a[i][k]*a[k][j])%MO;
        for (i=1;i<=2;i++)
            for (j=1;j<=2;j++)
        {
            a[i][j]=c[i][j];
            c[i][j]=0;
        }
    }

}

int main()
{

    int i,j,k;
    scanf("%d",&n);
    ksm(n-3);
    b[1][1]=2;b[1][2]=1;
    for (j=1;j<=2;j++)
        for (k=1;k<=2;k++) c[1][j]=(c[1][j]+b[1][k]*f[k][j])%MO;
    if (n==1) printf("1");
    else
    {
        if (n==2) printf("2");
        else printf("%d",c[1][1]);
    }

    return 0;
}
//醜數
/*把只包含因子2、3和5的數稱作醜數(Ugly Number)。
例如6、8都是醜數,但14不是,因爲它包含因子7。 
習慣上我們把1當做是第一個醜數。求按從小到大的順序的第N個醜數。*/
#include <iostream>  
#include <cstdio>  
using namespace std;  
#define min(a,b) ((a)<(b)?(a):(b))  
#define min4(a,b,c,d) min(min(a,b),min(c,d))  
int a[5850];  
int main()  
{  
    //freopen("data.in","r",stdin);  
    //freopen("data.out","w",stdout);  

    int n=1;  

    int p2,p3,p5,p7;  
    p2=p3=p5=p7=1;  
    a[1]=1;  
    while(n<5843)//枚舉5842個醜數,放在數組a裏。  
    {  
        a[++n]=min4(2*a[p2],3*a[p3],5*a[p5],7*a[p7]);//從現在枚舉的4個醜數裏,先選擇小的放在a裏。  
        if(a[n]==2*a[p2])p2++;//如果a[n]==2*a[p2],2*a[p2]可能是吧a[n]枚舉出的數,這樣p2++,也可能是重複的枚舉,這樣也是p2++,總之p2++。  
        if(a[n]==3*a[p3])p3++;//同理。  
        if(a[n]==5*a[p5])p5++;//同理。  
        if(a[n]==7*a[p7])p7++;//同理。  
    }  
    while(scanf("%d",&n)&&n)  
    {  
        printf("%d\n",a[n]);//要誰找誰。  
    }  
    return 0;  
}  
//求逆序對的個數
#include<stdio.h>

int a[10000];
int r[10000];
int n,ans;

void msort(int s,int t)
{
    int m,i,j,k;

    if (s==t) return;
    m=(s+t)>>1;
    msort(s,m);
    msort(m+1,t);
    i=s; j=m+1; k=s;
    while ((i<=m)&&(j<=t))
    {
        if (a[i]>a[j])
        {
            r[k]=a[i];
            i++;
            k++;
            ans+=t-j+1;
        }
        else
        {
            r[k]=a[j];
            j++;
            k++;
        }
    }
    while (i<=m)
    {
        r[k]=a[i];
        i++;
        k++;
    }
    while (j<=t)
    {
        r[k]=a[j];
        j++;
        k++;
    }
    for (i=s;i<=t;i++) a[i]=r[i];
}

int main()
{
    int i;

    printf("請輸入數列的長度:");
    scanf("%d",&n);
    printf("請輸入數列中的每一個元素,用空格隔開:");
    for (i=1;i<=n;i++) scanf("%d",&a[i]);

    msort(1,n);
    for (i=1;i<n;i++) printf("%d ",a[i]);
    printf("%d\n",a[i]);
    printf("%d",ans);

    return 0;
}

//鏈表反轉
/*輸入一個數列,存到鏈表裏面,然後把鏈表中節點前後反轉,使首尾對調,然後輸出*/
#include <stdio.h>
#include <stdlib.h>

struct node
{
    int data;
    node* next;
};
node* head1;
node* tail1;
node* head2;
node* tail2;

int main()
{
    int n, m;
    int i;
    int x;
    node* temp; //添加節點時的暫存節點
    node* p; //鏈表的遍歷元素
    node* q; //鏈表的遍歷元素
    //鏈表的head和tail都不存放數據
    head1 = (node*)malloc(sizeof(node));
    tail1 = (node*)malloc(sizeof(node));
    head1->next = tail1;
    tail1->next = NULL;
    p = head1;
    q = tail1;

    printf("請輸入鏈表的長度:");
    scanf("%d", &n);
    printf("請輸入每一個整數數據,用空格隔開:");
    for (int i=0; i<n; i++){
        scanf("%d", &x);
        temp = (node*)malloc(sizeof(node));
        temp->data = x;
        q = p->next;
        p->next = temp;
        temp->next = q;
        p = p->next;
    }

    tail2 = (node*)malloc(sizeof(node));
    tail2->next = NULL;
    temp = tail2;
    p = head1->next;
    while (p != tail1){
        q = p->next;
        p->next = temp;
        temp = p;
        p = q;
    }
    head2 = (node*)malloc(sizeof(node));
    head2->next = temp;
    free(head1);
    free(head2);

    printf("逆轉後的鏈表元素:");
    p = head2->next;
    while (p != tail2){
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");

    return 0;
}

//非遞減鏈表的合併
/*給出兩個不下降數列,存到鏈表裏面,然後合併兩個鏈表,要求合併之後任然是不下降序列*/
#include <stdio.h>
#include <stdlib.h>

struct node
{
    int data;
    node* next;
};
//第一個鏈表的首和尾
node* head1;
node* tail1;
//第二個鏈表的首和尾
node* head2;
node* tail2;

int main()
{
    int n, m;
    int i;
    int x;
    node* temp; //添加節點時的暫存節點
    node* p; //鏈表的遍歷元素
    node* q; //鏈表的遍歷元素
    node* t1; //鏈表的遍歷元素
    node* t2; //鏈表的遍歷元素
    //鏈表的head和tail都不存放數據
    head1 = (node*)malloc(sizeof(node));
    tail1 = (node*)malloc(sizeof(node));
    head1->next = tail1;
    tail1->next = NULL;
    p = head1;
    q = tail1;

    printf("請輸入第一個不下降鏈表的長度:");
    scanf("%d", &n);
    printf("請輸入每一個整數數據,用空格隔開:");
    for (int i=0; i<n; i++){
        scanf("%d", &x);
        temp = (node*)malloc(sizeof(node));
        temp->data = x;
        q = p->next;
        p->next = temp;
        temp->next = q;
        p = p->next;
    }

    head2 = (node*)malloc(sizeof(node));
    tail2 = (node*)malloc(sizeof(node));
    head2->next = tail2;
    tail2->next = NULL;
    p = head2;
    q = tail2;
    printf("請輸入第二個不下降鏈表的長度:");
    scanf("%d", &m);
    printf("請輸入每一個整數數據,用空格隔開:");
    for (int i=0; i<m; i++){
        scanf("%d", &x);
        temp = (node*)malloc(sizeof(node));
        temp->data = x;
        q = p->next;
        p->next = temp;
        temp->next = q;
        p = p->next;
    }

    //把第二個鏈表合併到第一個鏈表中
    t1 = head1;
    t2 = head2->next;
    while (t2!=tail2){
        while (t1!=tail1 && t1->next->data<t2->data) t1 = t1->next;
        p = t2;
        t2 = t2->next;
        q = t1->next;
        t1->next = p;
        p->next = q;
        t1 = t1->next;
    }
    free(head2);
    free(tail2);

    printf("合併後的鏈表元素:");
    p = head1->next;
    while (p != tail1){
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");

    return 0;
}

//歐拉回路
//如果圖G中的一個路徑包括每個邊恰好一次,則該路徑稱爲歐拉路徑(Euler path)
#include <stdio.h>
#define maxn 110

int v[maxn][maxn];
int vis[maxn][maxn];
int ans[maxn];
int n, m;
int s;

void eular(int x)
{
    int i;
    int y;
    for (i=1; i<=v[x][0]; i++){
        y = v[x][i];
        if (!vis[x][y]){
            vis[x][y] = 1;
            vis[y][x] = 1;
            eular(y);
            ans[0]++;
            ans[ans[0]] = y;
        }
    }
}

int main()
{
    int i;
    int x, y;

    printf("請輸入節點的數量:");
    scanf("%d", &n);
    printf("請輸入邊的數量:");
    scanf("%d", &m);
    printf("請輸入歐拉回路的起點:");
    scanf("%d", &s);
    for (i=0; i<m; i++){
        printf("請輸入第%d條邊的起點和終點:", i+1);
        scanf("%d%d", &x, &y);
        v[x][0]++;
        v[x][v[x][0]] = y;
        v[y][0]++;
        v[y][v[y][0]] = x;
    }

    eular(s);

    for (i=1; i<=ans[0]; i++) printf("%d ", ans[i]);
    printf("\n");

    return 0;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章