2022pta填空,函数

6-2 0/1背包问题(回溯法)

分数 20

全屏浏览题目

切换布局

作者 王东

单位 贵州师范学院

0/1背包问题。给定一载重量为W的背包及n个重量为wi、价值为vi的物体,1≤i≤n,要求而且重量和恰好为W具有最大的价值。

函数接口定义:

void dfs(int i,int tw,int tv,int rw,int op[]);

其中tw表示装入背包中的物品总重量,tv表示背包中物品总价值,op记录一个解向量。

裁判测试程序样例:

#include <stdio.h>#include <string.h>#include <iostream>#define MAXN 20 //最多物品数using namespace std;int n; //物品数int W; //限制重量int w[MAXN]={0}; //存放物品重量,不用下标0元素int v[MAXN]={0}; //存放物品价值,不用下标0元素int x[MAXN]; //存放最终解int maxv; //存放最优解的总价值void dfs(int i,int tw,int tv,int rw,int op[]);void dispasolution() //输出最优解{ int i; for (i=1;i<=n;i++) if (x[i]==1) printf("%d ",i); printf("\n%d %d",W,maxv);}int main(){ int i; cin>>n>>W; //输入物体个数及背包载重量 for(int i=1;i<=n;i++)//输入各物体重量及价值 cin>>w[i]>>v[i]; int op[MAXN]; //存放临时解 memset(op,0,sizeof(op)); int rw=0; for (int i=1;i<=n;i++) rw+=w[i]; dfs(1,0,0,rw,op); dispasolution(); return 0;}/* 请在这里填写答案 */

输入格式:

第一行输入背包载重量W及背包个数n,再依次输入n行,每行为背包重量wi和价值vi。

输出格式:

第一行输出输出装入背包内的物体编号(末尾有空格),第二行输出背包内的物体总重量和总价值。

输入样例1:

5 10

2 6

2 3

6 5

5 4

4 6

输出样例1:

1 2 3 

10 14 

 

void dfs(int i,int tw,int tv,int rw,int op[]) //求解0/1背包问题

{

    int j;

    if (i>n) //找到一个叶子结点

    { if (

tw==W && tv>maxv

) //找到一个满足条件的更优解,保存它

        { maxv=tv;

            for (

j=1;j<=n;j++

) //复制最优解

                x[j]=op[j];

        }

    }

    else //尚未找完所有物品

    { if (

tw+w[i]<=W

) //左孩子结点剪枝:满足条件时才放入第i个物品

        {

            op[i]=1; //选取第i个物品

            dfs(

i+1,tw+w[i],tv+v[i],rw-w[i],op

);

        }

        op[i]=0; //不选取第i个物品,回溯

        if (

tw+rw>W

) //右孩子结点剪枝

            dfs(

i+1,tw,tv,rw-w[i],op

);

    }

}

 

 

 

 

 

6-3 快速排序(分治法)

分数 10

全屏浏览题目

切换布局

作者 王东

单位 贵州师范学院

快速排序(分治法)

函数接口定义:

int Partition(SqList &L,int low,int high);//实现一趟划分。void QSort(SqList &L,int low,int high);

裁判测试程序样例:

#include <iostream>#define MAXSIZE 1000using namespace std;typedef struct{ int key; char *otherinfo;}ElemType; typedef struct{ ElemType *r; int length;}SqList;int Partition(SqList &L,int low,int high);void QSort(SqList &L,int low,int high);void Create_Sq(SqList &L){ int i,n; cin>>n; //输入的值不大于 MAXSIZE for(i=1;i<=n;i++) { cin>>L.r[i].key; L.length++; }}void show(SqList L){ int i; for(i=1;i<=L.length;i++) if(i==1) cout<<L.r[i].key; else cout<<" "<<L.r[i].key;}int main(){ SqList L; L.r=new ElemType[MAXSIZE+1]; L.length=0; Create_Sq(L); QSort(L,1,L.length); show(L); return 0;}/* 请在这里填写答案 */

输入样例:

第一行输入一个数n,接下来输入n个数。

7

24 53 45 45 12 24 90

输出样例:

输出按升序排序的结果。

12 24 24 45 45 53 90

代码长度限制

16 KB

时间限制

400 ms

内存限制

 

 

int Partition(SqList &L,int low,int high)

  int pivotkey;

  L.r[0]=L.r[low]; 

  pivotkey=L.r[low].key;

  while(

low<high

)

  {

    while(

low<high&&L.r[high].key>=pivotkey

) --high;

    L.r[low]=L.r[high];    

    while(

low<high&&L.r[low].key<=pivotkey

) ++low;

    L.r[high]=L.r[low];

  }

  L.r[low]=L.r[0];

  return low;

}

 

void QSort(SqList &L,int low,int high)

{

  int pivotloc;

  if(low<high)

   {                                        

    pivotloc=

pivotloc= Partition(L,low,high)

;

    

QSort(L,low,pivotloc-1)

;

    

QSort(L,pivotloc+1,high)

;

   }

}

 

void QuickSort(SqList &L)

{

   QSort(L,1,L.length);

}

 

 

6-4 棋盘覆盖问题(分治法)

分数 20

全屏浏览题目

切换布局

作者 王东

单位 贵州师范学院

用分治法求解棋盘覆盖问题。有一个2k×2k(k>0)的棋盘,恰好有一个方格与其他方格不同,称之为特殊方格。现在要用如下的L型骨牌覆盖除了特殊方格外的其他全部方格,骨牌可以任意旋转,并且任何两个骨牌不能重叠。请给出一种覆盖方法。

 

函数接口定义:

void ChessBoard(int tr,int tc,int dr,int dc,int size);(tr,tc)表示一个象限左上角方格的坐标,(dr,dc)是特殊方格所在的坐标。size是棋盘的行数和列数。

裁判测试程序样例:

#include <iostream>#include<fstream>#include <iomanip>#define MAX 1025using namespace std;int board[MAX][MAX];int tile=1;void ChessBoard(int tr,int tc,int dr,int dc,int size);int main(){int dr,dc,size;int j,i;cin>>size;cin>>dr>>dc;ChessBoard(0,0,dr,dc,size);for(i=0;i<size;i++){ cout<<left; for(j=0;j<size;j++) { cout<<setfill(' ')<<setw(5)<<board[i][j]; } cout<<endl;}return 0;} /* 请在这里填写答案 */

输入样例:

第一行输入一个数n表示棋盘大小,第二行输入特殊方格的行列下标。

8

1 2

输出样例:

输出棋盘。

3 3 4 4 8 8 9 9    

3 2 0 4 8 7 7 9    

5 2 2 6 10 10 7 11   

5 5 6 6 1 10 11 11   

13 13 14 1 1 18 19 19   

13 12 14 14 18 18 17 19   

15 12 12 16 20 17 17 21   

15 15 16 16 20 20 21 21   

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

 

 

void ChessBoard(int tr,int tc,int dr,int dc,int size)

{ if(

size==1

) return; //递归出口

    int t=tile++; //取一个L型骨,其牌号为tile

    int s=size/2; //分割棋盘

    //考虑左上角象限

    if(

dr<tr+s&&dc<tc+s

) //特殊方格在此象限中

      

ChessBoard(tr,tc,dr,dc,s)

;

    else //此象限中无特殊方格

    {    

board[tr+s-1][tc+s-1]=t

; //用t号L型骨牌覆盖右下角

        

ChessBoard(tr,tc,tr+s-1,tc+s-1,s)

; //将右下角作为特殊方格继续处理该象限

    }

    //考虑右上角象限

    if(

dr<tr+s&&dc>=tc+s

)  

       

ChessBoard(tr,tc+s,dr,dc,s)

; //特殊方格在此象限中 

    else //此象限中无特殊方格

    {    

board[tr+s-1][tc+s]=t

; //用t号L型骨牌覆盖左下角

    

ChessBoard(tr,tc+s,tr+s-1,tc+s,s)

; //将左下角作为特殊方格继续处理该象限

    }

   //处理左下角象限

    if(

dr>=tr+s&&dc<tc+s

) //特殊方格在此象限中

       

ChessBoard(tr+s,tc,dr,dc,s)

;  

    else //此象限中无特殊方格

    {   

board[tr+s][tc+s-1]=t

; //用t号L型骨牌覆盖右上角

        

ChessBoard(tr+s,tc,tr+s,tc+s-1,s)

; //将右上角作为特殊方格继续处理该象限

    }

    //处理右下角象限

    if(

dr>=tr+s&&dc>=tc+s

) //特殊方格在此象限中

        

ChessBoard(tr+s,tc+s,dr,dc,s)

    else //此象限中无特殊方格

    {    

board[tr+s][tc+s]=t

; //用t号L型骨牌覆盖左上角

       

ChessBoard(tr+s,tc+s,tr+s,tc+s,s)

; //将左上角作为特殊方格继续处理该象限

    }

}

 

6-5 求解活动安排问题(贪心法)

分数 10

全屏浏览题目

切换布局

作者 王东

单位 贵州师范学院

假设有一个需要使用某一资源的n个活动所组成的集合S,S={1,…,n}。该资源任何时刻只能被一个活动所占用,活动i有一个开始时间bi和结束时间ei(bi<ei),其执行时间为ei-bi,假设最早活动执行时间为0。

一旦某个活动开始执行,中间不能被打断,直到其执行完毕。若活动i和活动j有bi≥ej或bj≥ei,则称这两个活动兼容。

设计算法求一种最优活动安排方案,使得所有安排的活动个数最多。

函数接口定义:

void solve();

裁判测试程序样例:

#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;#define MAX 51//问题表示struct Action{ int b; //活动起始时间 int e; //活动结束时间 bool operator<(const Action &s) const //重载<关系函数 { return e<=s.e; //用于按活动结束时间递增排序 }};int n;Action A[MAX]; bool flag[MAX]; //标记选择的活动int Count=0; //选取的兼容活动个数void solve();int main(){ cin>>n; for (int i=0;i<n;i++) cin>>A[i].b>>A[i].e; solve(); for (int i=0;i<n;i++) if (flag[i]) { printf("[%d,%d]\n",A[i].b,A[i].e); Count++; } cout<<Count; return 0;}/* 请在这里填写答案 */

输入格式:

第一行是一个整数n,接着的n行中每一行包括两个整数b和e,其中b是一个订单开始时间,e是的结束时间。。

输出格式:

若count表示最大兼容活动集合数,先输出count行,每行为活动的开始时间和结束时间。最后输出count。

输入样例1:

11

1 4

3 5

0 6

5 7

3 8

5 9

6 10

8 11

8 12

2 13

12 15

输出样例1:

[1,4]

[5,7]

[8,11]

[12,15]

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

 

 

void solve() //求解最大兼容活动子集

{

    memset(flag,0,sizeof(flag));//初始化为false

    sort(A,A+n); //A[1..n]按活动结束时间递增排序

    int preend=0; //前一个兼容活动的结束时间

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

    { if (

A[i].b>=preend

)

        {    

flag[i]=true

;        

            

preend=A[i].e

;

        }

    }

}

 

6-6 最小生成树(克鲁斯卡尔算法)

分数 10

全屏浏览题目

切换布局

作者 王东

单位 贵州师范学院

试实现克鲁斯卡尔最小生成树算法。

函数接口定义:

void Kruskal(AMGraph G);

其中 G 是基于邻接矩阵存储表示的无向图。

裁判测试程序样例:

#include <stdio.h>#define MVNum 10 #define MaxInt 32767 typedef struct{ char vexs[MVNum]; int arcs[MVNum][MVNum]; int vexnum,arcnum; }AMGraph;struct Evode{ char Head; char Tail; int lowcost;}Edge[(MVNum * (MVNum - 1)) / 2];int Vexset[MVNum];void CreateUDN(AMGraph &G);//实现细节隐藏void Kruskal(AMGraph G);int main(){ AMGraph G; CreateUDN(G); Kruskal(G); return 0;}/* 请在这里填写答案 */

输入样例:

第1行输入结点数vexnum和边数arcnum。第2行输入vexnum个字符表示结点的值,接下来依次输入arcnum行,每行输入3个值,前两个字符表示结点,后一个数表示两个结点之间边的权值。

7 9

0123456

0 1 28

0 5 10

1 2 16

1 6 14

2 3 12

3 6 18

3 4 22

4 5 25

4 6 24

输出样例:

按最小生成树的生成顺序输出每条边。

0->5

2->3

1->6

1->2

3->4

4->5 

 

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

窗体顶端

C++ (g++)

 

 

1

#include<bits/stdc++.h>

2

using namespace std;

3

int cmp(Evode a,Evode b)

4

{

5

    return a.lowcost<b.lowcost;

6

}

7

8

int find(char x)//找父亲

9

{

10

    int y;

11

    y = int(x)-int('0');

12

    while(Vexset[y]!=y)y=Vexset[y];

13

    return y;

14

}

15

16

int add(char x,char y)//判断是否为同一个父亲,不是就加到一起

17

{

18

    if(find(x)==find(y))return 0;

19

    else

20

    {

21

        int fx = find(x);

22

        int fy = find(y);

23

        Vexset[fx]=fy;

24

        return 1;

25

    }

26

}

27

28

void Kruskal(AMGraph G)

29

{

30

    for(int i=0;i<G.vexnum;i++)

31

    {

32

        Vexset[int(G.vexs[i])-int('0')]=int(G.vexs[i])-int('0');//开始的父亲就是自己

33

    }

34

    

35

    sort(Edge,Edge+G.arcnum,cmp);//按结构体中路径长短排序

36

    

窗体底端

测试用例

 

上一题

 

查看上次提交

提交本题作答

 

下一题

 

#include<bits/stdc++.h>

using namespace std;

int cmp(Evode a,Evode b)

{

    return a.lowcost<b.lowcost;

}

 

int find(char x)//找父亲

{

    int y;

    y = int(x)-int('0');

    while(Vexset[y]!=y)y=Vexset[y];

    return y;

}

 

int add(char x,char y)//判断是否为同一个父亲,不是就加到一起

{

    if(find(x)==find(y))return 0;

    else

    {

        int fx = find(x);

        int fy = find(y);

        Vexset[fx]=fy;

        return 1;

    }

}

 

void Kruskal(AMGraph G)

{

    for(int i=0;i<G.vexnum;i++)

    {

        Vexset[int(G.vexs[i])-int('0')]=int(G.vexs[i])-int('0');//开始的父亲就是自己

    }

    

    sort(Edge,Edge+G.arcnum,cmp);//按结构体中路径长短排序

    

    for(int i=0;i<G.arcnum;i++)

    {

        if(add(Edge[i].Head,Edge[i].Tail))

        {

           printf("%c->%c\n",Edge[i].Head,Edge[i].Tail);

        }

 

    }

}

 

 

 

6-7 求解最长递增子序列问题(动态规划法)

分数 10

全屏浏览题目

切换布局

作者 王东

单位 贵州师范学院

求解最长递增子序列问题。给定一个无序的整数序列a[0..n-1],求其中最长递增子序列的长度(不一定连续)。

函数接口定义:

void IncreaseOrder(int a[],int dp[],int x[][N],int n);

裁判测试程序样例:

#include<bits/stdc++.h>#include<iostream>#define N 100 using namespace std;void IncreaseOrder(int a[],int dp[],int x[][N],int n);int main(){ //dp[i]表示a[0..i]中以a[i]结尾的最长递增子序列的长度 //X[i][0..dp[i]-1]表示以a[i]结尾的最长递增子序列 int A[N],dp[N],X[N][N]; int n,i,index; cin>>n; for(i=0;i<n;i++) cin>>A[i]; IncreaseOrder(A,dp,X,n); for (index = 0, i = 1; i < n; i++) //求所有递增子序列的最大长度 if (dp[index] < dp[i]) index = i; cout<<dp[index]<<endl; for (i = 0; i < dp[index]; i++) //输出最长递增子序列 cout<<X[index][i]<<" "; return 0;}/* 请在这里填写答案 */

输入格式:

第一行为正整数n,表示序列元素个数,第二行依次输入n个数。

9

2 1 5 3 6 4 8 9 7

输出格式:

输出最长递增子序列的长度及序列。

5

2 5 6 8 9 

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

 

 

void IncreaseOrder(int a[],int dp[],int x[][N],int n)

{

int i, j, k, index;

 

for (i = 0; i < n; i++) //依次计算a[0]~a[i]的最长递增子序列

{

dp[i] = 1;

x[i][0] = a[i];

int max = 1;

int maxindex=i; //初始化递增子序列长度的最大值

    for(int j = 0;j < i;j ++) {

if ((a[j] < a[i]) && (max<dp[j]+1)){

 

max = dp[j]+1;

maxindex=j;

}

}

if(maxindex!=i){

dp[i] = max;

for (k = 0; k < max-1; k++) //存储最长递增子序列

x[i][k] = x[maxindex][k];

x[i][max-1]= a[i];

}

}

}

 

 

6-8 最短路径(弗洛伊德算法)

分数 10

全屏浏览题目

切换布局

作者 王东

单位 贵州师范学院

试实现弗洛伊德最短路径算法。

函数接口定义:

void ShortestPath_Floyed(AMGraph G);

其中 G 是基于邻接矩阵存储表示的有向图。

裁判测试程序样例:

#include <iostream>using namespace std;#define MaxInt 32767#define MVNum 100typedef char VerTexType; typedef int ArcType;int Path[MVNum][MVNum]; int D[MVNum][MVNum];typedef struct{ VerTexType vexs[MVNum]; ArcType arcs[MVNum][MVNum]; int vexnum,arcnum; }AMGraph;void CreateUDN(AMGraph &G);//实现细节隐藏void ShortestPath_Floyed(AMGraph G);void DisplayPath(AMGraph G , int begin ,int temp ){ if(Path[begin][temp] != -1){ DisplayPath(G , begin ,Path[begin][temp]); cout << G.vexs[Path[begin][temp]] << "->"; }}int main(){ AMGraph G; char start , destination; int num_start , num_destination; CreateUDN(G); ShortestPath_Floyed(G); cin >> start >> destination; num_start = LocateVex(G , start); num_destination = LocateVex(G , destination); DisplayPath(G , num_start , num_destination); cout << G.vexs[num_destination]<<endl; cout << D[num_start][num_destination]; return 0;}/* 请在这里填写答案 */

输入样例:

第1行输入结点数vexnum和边数arcnum。第2行输入vexnum个字符表示结点的值,接下来依次输入arcnum行,每行输入3个值,前两个字符表示结点,后一个数表示两个结点之间边的权值。最后一行输入源点及终点。

6 8

012345

0 5 100

0 2 10

0 4 30

1 2 5

2 3 50

3 5 10

4 3 20

4 5 60

0 5

输出样例:

第一行输出源点到终点的最短路径,第二行输出源点到终点的最短路径距离。

0->4->3->5

60

 

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

窗体顶端

C++ (g++)

 

 

1

void ShortestPath_Floyed(AMGraph G){ 

2

    int i , j , k ;

3

    for (i = 0; i < G.vexnum; ++i)

4

        for(j = 0; j < G.vexnum; ++j){ 

5

            D[i][j] = 

6

G.arcs[i][j]

7

8

            if(D[i][j] < MaxInt && i != j) 

9

Path[i][j]=i

10

11

            else Path [i][j] = -1; 

12

        }

13

    for(k = 0; k < G.vexnum; ++k) 

14

        for(i = 0; i < G.vexnum; ++i) 

15

            for(j = 0; j < G.vexnum; ++j)

16

                if(

17

D[i][k] + D[k][j]

18

 < D[i][j]){

19

                    D[i][j] = 

20

D[i][k]+D[k][j]

21

;

22

                    Path[i][j] =

23

Path[k][j]

24

25

                }

26

}

窗体底端

测试用例

 

上一题

 

查看上次提交

提交本题作答

 

下一题

 

void ShortestPath_Floyed(AMGraph G){ 

    int i , j , k ;

    for (i = 0; i < G.vexnum; ++i)

        for(j = 0; j < G.vexnum; ++j){ 

            D[i][j] = 

G.arcs[i][j]

            if(D[i][j] < MaxInt && i != j) 

Path[i][j]=i

            else Path [i][j] = -1; 

        }

    for(k = 0; k < G.vexnum; ++k) 

        for(i = 0; i < G.vexnum; ++i) 

            for(j = 0; j < G.vexnum; ++j)

                if(

D[i][k] + D[k][j]

 < D[i][j]){

                    D[i][j] = 

D[i][k]+D[k][j]

;

                    Path[i][j] =

Path[k][j]

                }

}

 

 

 

6-9 求解图的m着色问题(回溯法)

分数 10

全屏浏览题目

切换布局

作者 王东

单位 贵州师范学院

给定无向连通图G和m种不同的颜色。用这些颜色为图G的各顶点着色,每个顶点着一种颜色。如果有一种着色法使G中每条边的两个顶点着不同颜色,则称这个图是m可着色的。图的m着色问题是对于给定图G和m种颜色,找出所有不同的着色法。

函数接口定义:

void dfs(int i);

裁判测试程序样例:

#include <stdio.h>#include <string.h>#define MAXN 20 //图最多的顶点个数int n,k,m;int a[MAXN][MAXN];int count=0; //全局变量,累计解个数int x[MAXN]; //全局变量,x[i]表示顶点i的着色bool Same(int i) //判断顶点i是否与相邻顶点存在相同的着色{ for (int j=1;j<=n;j++) if (a[i][j]==1 && x[i]==x[j]) return false; return true;}int main(){ memset(a,0,sizeof(a)); //a初始化 memset(x,0,sizeof(x)); //x初始化 int x,y; scanf("%d%d%d",&n,&k,&m); //输入n,k,m for (int j=1;j<=k;j++) { scanf("%d%d",&x,&y); //输入一条边的两个顶点 a[x][y]=1; //无向图的边对称 a[y][x]=1; } dfs(1); //从顶点1开始搜索 if (count>0) //输出结果 printf("%d",count); else printf("-1"); return 0;}/* 请在这里填写答案 */

输出格式:

程序运行结束时,将计算出的不同的着色方案数输出。如果不能着色,程序输出-1。

输入样例:

5 8 4

1 2

1 3

1 4

2 3

2 4

2 5

3 4

4 5

输出样例:

48

代码长度限制

16 KB

时间限制

400 ms

内存限制

 

 

void dfs(int i) //求解图的m着色问题

{

    if (i>n)                    

    {

        

count++

;            

    }

    else

    {

        for (int j=1;j<=m;j++)    

        {

            x[i]=j;

            if (

Same(i)

)        

                dfs(i+1);

            

x[i]=0

;            

        }

    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值