ACM算法相关资料

ACM算法相关资料

一:知识点

数据结构:

1,单,双链表及循环链表

2,树的表示与存储,二叉树(概念,遍历)二叉树的

应用(二叉排序树,判定树,博弈树,解答树等)

3,文件操作(从文本文件中读入数据并输出到文本文

件中)

4,图(基本概念,存储结构,图的运算)

数学知识

1,离散数学知识的应用(如排列组合、简单的图论,数理逻辑)

2,数论知识

3,线性代数

4,组合代数

5,计算几何

算法

1,排序算法(冒抛法,插入排序,合并排序,快速排序,堆排序)

2,查找(顺序查找,二分发)

3,回溯算法

4,递归算法

5,分治算法

6,模拟法

7,贪心法

8,简单搜索算法(深度优先,广度优先),搜索中的剪枝,A*算法

9,动态规划的思想及基本算法

10,高精度运算

三、ACM竞赛的题型分析

竞赛的程序设计一般只有16种类型,它们分别是:

Dynamic Programming (动态规划)

Greedy (贪心算法)

Complete Search (穷举搜索)

Flood Fill (不知该如何翻译)

Shortest Path (最短路径)

Recursive Search Techniques (回溯搜索技术)

Minimum Spanning Tree (最小生成树)

Knapsack (背包问题)

Computational Geometry (计算几何学)

Network Flow (网络流)

Eulerian Path (欧拉回路)

Two-Dimensional Convex Hull (不知如何翻译)

BigNums (大数问题)

Heuristic Search (启发式搜索)

Approximate Search (近似搜索)

Ad Hoc Problems (杂题)

 

一:递归与分治

1. 二分查找

2. 合并排序

3. 快速排序

二:回溯

1. 0-1背包问题

2. 装载问题

3. 堡垒问题(ZOJ1002

4. *翻硬币问题

5. 8皇后问题

6. 素数环问题

7. 迷宫问题

8. *农场灌溉问题(ZOJ2412

9. *求图像的周长(ZOJ1047

10. *骨牌矩阵

11. *字母转换(ZOJ1003

12. *踩气球(ZOJ1004

三:搜索

1. Floodfill

2. 电子老鼠闯迷宫

3. 跳马

4. 独轮车

5. 皇宫小偷

6. 分酒问题

7. *找倍数

8. *8数码难题

四:动态规划

1. 最长公共子序列

2. 计算矩阵连乘积

3. 凸多边形的最优三角剖分

4. 防卫导弹

5. *石子合并

6. *最小代价子母树

7. *旅游预算

8. *皇宫看守

9. *游戏室问题

10. *基因问题

11. *田忌赛马

五:贪心与随机算法

1. 背包问题

2. 搬桌子问题

3. *照亮的山景

4. *用随即算法求解8皇后问题

5. 素数测试

 

习题

1 0-1背包问题

0 / 1背包问题中,需对容量为c 的背包进行装载。从n 个物品中选取装入背包的物品,每件物品i 的重量为wi ,价值为pi 。对于可行的背包装载,背包中物品的总重量不能超过背包的容量,最佳装载是指所装入的物品价值最高。

程序如下:

#include <stdio.h>

void readdata();

void search(int);

void checkmax();

void printresult();

int c=35, n=10; //c 背包容量;n:物品数

int w[10], v[10]; //w[i]v[i]:第i件物品的重量和价值

int a[10], max; //a数组存放当前解各物品选取情况;max:记录最大价值

//a[i]=0表示不选第i件物品,a[i]=1表示选第i件物品

int main()

{

    readdata(); //读入数据

    search(0); //递归搜索

    printresult();

}

void search(int m)

{

    if(m>=n)

        checkmax(); //检查当前解是否是可行解,若是则把它的价值与max比较

    else

    {

        a[m]=0; //不选第m件物品

        search(m+1); //递归搜索下一件物品

        a[m]=1; //不选第m件物品

        search(m+1); //递归搜索下一件物品

    }

}

void checkmax()

{

    int i, weight=0, value=0;

    for(i=0;i<n;i++)

    {

        if(a[i]==1) //如果选取了该物品

        {

            weight = weight + w[i]; //累加重量

            value = value + v[i]; //累加价值

        }

    }

    if(weight<=c) //若为可行解

        if(value>max) //且价值大于max

            max=value; //替换max

}

void readdata()

{

    int i;

    for(i=0;i<n;i++)

        scanf("%d%d",&w[i],&v[i]); //读入第i件物品重量和价值

}

void printresult()

{

    printf("%d",max);

}

 

2 装载问题

有两艘船,载重量分别是c1 c2n个集装箱,重量是wi (i=1…n),且所有集装箱的总重量不超过c1+c2。确定是否有可能将所有集装箱全部装入两艘船。

提示:求出不超过c1的最大值max,若总重量-max < c2则能装入到两艘船。

 

3 堡垒问题(ZOJ1002

如图城堡是一个4×4的方格,为了保卫城堡,现需要在某些格子里修建一些堡垒。城堡中的某些格子是墙,其余格子都是空格,堡垒只能建在空格里,每个堡垒都可以向上下左右四个方向射击,如果两个堡垒在同一行或同一列,且中间没有墙相隔,则两个堡垒都会把对方打掉。问对于给定的一种状态,最多能够修建几个堡垒。

程序主要部分如下:

int main()

{

    readdata(); //读入数据

    search(0); //递归搜索

    printresult();

}

void search(int m)

{

    int row, col;

    row=m/n; //求第m个格子的行号

    col=m%n; //求第m个格子的列号

    if(m>=n*n)

        checkmax(); //检查当前解是否是可行解,若是则把它的价值与max比较

    else

    {

        search(m+1); //该位置不放堡垒递归搜索下一个位置

        if(canplace(m)) //判断第m个格子是否能放堡垒

            {

            place(m); //在第m个格子上放置一个堡垒

            search(m+1); //递归搜索下一个位置

            takeout(m); //去掉第m个格子上放置的堡垒

        }

    }

}

 

4 翻硬币问题

把硬币摆放成32×9的矩阵,你可以随意翻转矩阵中的某些行和某些列,问正面朝上的硬币最多有多少枚?

提示:(1)任意一行或一列,翻两次等于没有翻;

2)对于9列的任何一种翻转的情况,每一行翻与不翻相互独立。

 

5 8皇后问题

在一个8×8的棋盘里放置8个皇后,要求这8个皇后两两之间互相都不冲突

#include <stdio.h>

#include <math.h>

void search(int);

void printresult(); //打印结果

int canplace(int,int); //判断该位置能否放置皇后

void place(int,int); //在该位置能否放置皇后

void takeout(int,int); //把该位置放置皇后去掉

int a[8]; //a[i]存放第i个皇后的位置

int main()

{

    search(0); //递归搜索

}

void search(int m)

{

    int i;

    if(m>=8) //当已经找出一组解时

        printresult(); //输出当前结果

    else

    {

        for(i=0;i<8;i++) //对当前行07列的每一个位置

        {

            if(canplace(m,i)) //判断第m个格子是否能放堡垒

            {

                place(m,i); //(m,i)格子上放置一个皇后

                search(m+1); //递归搜索下一行

                takeout(m,i); //(m,i)格子上的皇后去掉

            }

        }

    }

}

int canplace(int row, int col)

{

    int i;

    for(i=0;i<row;i++)

        if(abs(i-row)==abs(a[i]-col)||a[i]==col)

            return(0);

    return(1);

}

void place(int row, int col)

{

    a[row]=col;

}

void takeout(int row, int col)

{

    a[row]=-1;

}

void printresult()

{

    int i,j;

    for(i=0;i<8;i++)

    {

        for(j=0;j<8;j++)

            if(a[i]==j)

                printf(" A ");

            else

                printf(" . ");

        printf("/n");

    }

    printf("/n");

}

 

6 素数环问题

把从12020个数摆成一个环,要求相邻的两个数的和是一个素数。

分析:用回溯算法,考察所有可能的排列。

程序如下:

#include <stdio.h>

#include <math.h>

 

void search(int);

void init();            //初始化

void printresult();     //打印结果

int isprime(int);       //判断该数是否是素数

void swap(int,int);     //交换a[m]a[i]

int a[21];        //a数组存放素数环

 

int main()

{

    init();

    search(2); //递归搜索

}

int isprime(int num)

{

    int i,k;

    k=sqrt(num);

    for(i=2;i<=k;i++)

        if(num%i==0)

            return(0);

    return(1);

}

void printresult()

{

    int i;

    for(i=1;i<=20;i++)

        printf("=",a[i]);

    printf("/n");

}

void search(int m)

{

    int i;

    if(m>20) //当已经搜索到叶结点时

    {

        if(isprime(a[1]+a[20])) //如果a[1]+a[20]也是素数

            printresult(); //输出当前解

        return;

    }

    else

    {

    for(i=m;i<=20;i++) //(排列树)

    {

        swap(m,i); //交换a[m]a[i]

        if(isprime(a[m-1]+a[m])) //判断a[m-1]+a[m]是否是素数

            search(m+1); //递归搜索下一个位置

        swap(m,i); //a[m]a[i]换回来

    }

}

}

void swap(int m, int i)

{

    int t;

    t=a[m];

    a[m]=a[i];

    a[i]=t;

}

void init()

{

    int i;

    for(i=0;i<21;i++)

        a[i]=i;

}

 

7

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值