《算法竞赛入门经典》动态规划复习

codevs 4979 数塔

 1 #define N 100
 2 #include<iostream>
 3 using namespace std;
 4 #include<cstdio>
 5 int a[N][N],b[N][N],n;
 6 int main()
 7 {
 8     scanf("%d",&n);
 9     for(int i=1;i<=n;++i)
10       for(int j=1;j<=i;++j)
11       {
12           scanf("%d",&a[i][j]);
13           b[i][j]=a[i][j];
14       }
15     for(int i=n-1;i>=1;--i)
16       for(int j=1;j<=i;++j)
17       {
18           if(a[i+1][j]>=a[i+1][j+1])
19             a[i][j]+=a[i+1][j];
20           else a[i][j]+=a[i+1][j+1];
21       }
22     int cont=1;
23     printf("%d\n",a[1][1]);
24     printf("%d-",b[1][1]);
25 /*这个输出路径的方式很有意思,选择的路径根据a的性质,而且每次右移之后,就不可能再向左了,所以要cont++*/
26     for(int i=1;i<=n-1;++i)
27     {
28         if(a[i+1][cont]>=a[i+1][cont+1])
29           printf("%d",b[i+1][cont]);
30         else{
31             printf("%d",b[i+1][++cont]);
32         }
33         if(i!=n-1) printf("-");
34     }
35     return 0;
36 }

cogs

cogs 1243. 嵌套矩形

★★   输入文件:qiantao.in   输出文件:qiantao.out   简单对比
时间限制:1 s   内存限制:128 MB

【题目描述】

有 n 个矩形,每个矩形可以用两个整数 a, b 描述,表示它的长和宽。矩形 X(a, b) 可以嵌套在矩形 Y(c, d) 中当且仅当 a<c, b<d,或者 b<c, a<d(相当于把矩形 X 旋转了 90°)。例如 (1, 5) 可以嵌套在 (6, 2) 内,但不能嵌套在 (3, 4) 内。

你的任务是选出尽量多的矩形,使得除了最后一个之外,每一个矩形都可以嵌套在下一个矩形内。

【输入格式】

第一行一个正整数 n (n <= 1000)。

接下来 n 行每行两个正整数 a, b 表示矩形 i 的长和宽。

【输出格式】

第一行一个整数 k 表示符合条件的最多矩形数。

第二行 k 个整数依次表示符合条件矩形的编号,要求字典序最小。

【样例输入】

8
14 9
15 19
18 12
9 10
19 17
15 9
2 13
13 10

【样例输出】

4
4 8 3 2

【样例说明】

最大嵌套深度为 4 。

4 个矩形分别是:4(9, 10) < 8(13, 10) < 3(18,12) < 2(15,19)

【来源】

算法竞赛入门经典 例题 9-2

 1 #define N 1002
 2 #include<iostream>
 3 using namespace std;
 4 #include<cstdio>
 5 bool G[N][N]={0};
 6 int n;
 7 struct Jx{
 8     int a, b;
 9 }jx[N];
10 int d[N]={0};
11 void input()
12 {
13     scanf("%d",&n);
14     for(int i=1;i<=n;++i)
15       scanf("%d%d",&jx[i].a,&jx[i].b);
16 }
17 void build_tu()
18 {
19     for(int i=1;i<=n;++i)
20       for(int j=1;j<i;++j)
21       {
22           if(jx[i].a>jx[j].a&&jx[i].b>jx[j].b)
23           {
24               G[j][i]=true;
25           }
26         if(jx[i].a>jx[j].b&&jx[i].b>jx[j].a)
27           {
28               G[j][i]=true;
29           }
30         if(jx[i].a<jx[j].a&&jx[i].b<jx[j].b)
31           {
32               G[i][j]=true;
33           }
34         if(jx[i].a<jx[j].b&&jx[i].b<jx[j].a)
35           {
36               G[i][j]=true;
37           }
38       }
39 }
40 int dp(int k)
41 {
42     int &js=d[k];
43     if(js>0) return d[k];
44     d[k]=1;
45     for(int j=1;j<=n;++j)
46       if(G[k][j])
47       js=max(js,dp(j)+1);
48     return js;
49 }
50 void prin(int k)
51 {
52     printf("%d ",k);
53     for(int i=1;i<=n;++i)
54     {
55         if(G[k][i]&&d[i]+1==d[k])
56         {
57             prin(i);
58             break;
59         }
60     }
61 }
62 int main()
63 {
64     freopen("qiantao.in","r",stdin);
65     freopen("qiantao.out","w",stdout);
66     input();
67     build_tu();
68     int ans=0,k;
69     for(int i=1;i<=n;++i)
70     {
71         if(dp(i)>ans)
72         {
73             k=i;
74             ans=d[i];
75         }
76     }
77     printf("%d\n",ans);
78     prin(k);
79     fclose(stdin);
80     fclose(stdout);
81     return 0;
82 }

TYVJ P1214 硬币问题

时间: 1000ms / 空间: 131072KiB / Java类名: Main

描述

有n种硬币,面值为别为a[1],a[2],a[3]……a[n],每种都有无限多。给定非负整数s,可以选取多少个硬币使得面值和恰好为s?输出硬币数目最小值和最大值

输入格式

第1行n
第2行s
第3到n+2行为n种不同的面值

输出格式

第1行为最小值
第2行为最大值

测试样例1

输入





3

输出


6

备注

1<=n<=100
1<=s<=10000
1<=a[i]<=s

 1 /*背包问题的变式*/
 2 #include<iostream>
 3 using namespace std;
 4 #include<cstdio>
 5 #include<cstring>
 6 #define N 105
 7 #define S 10010
 8 int n,s,a[N];
 9 int minv[S],maxv[S];
10 int main()
11 {
12     scanf("%d%d",&n,&s);
13     for(int i=1;i<=n;++i)
14       scanf("%d",&a[i]);
15     memset(minv,99,sizeof(minv));
16     memset(maxv,-99,sizeof(maxv));
17     minv[0]=maxv[0]=0;
18     for(int i=1;i<=s;++i)
19       for(int j=1;j<=n;++j)
20       if(i>=a[j])
21       {
22           minv[i]=min(minv[i],minv[i-a[j]]+1);
23             maxv[i]=max(maxv[i],maxv[i-a[j]]+1);
24       }
25     printf("%d\n%d",minv[s],maxv[s]);
26     return 0;
27 }

UVA - 437 The Tower of Babylon

 1 #define N 100
 2 #include<cstring>
 3 #include<iostream>
 4 using namespace std;
 5 #include<cstdio>
 6 bool G[N][N];
 7 int d[N],n,t=0;
 8 struct Lf{
 9     int x,y,z;
10 }lf[N];
11 void input()
12 {
13     memset(G,false,sizeof(G));
14     memset(d,0,sizeof(d));
15     int x,y,z;
16     t=0;
17     for(int i=1;i<=n;++i)
18     {
19         scanf("%d%d%d",&x,&y,&z);
20         ++t;
21         lf[t].x=x;lf[t].y=y;lf[t].z=z;
22         ++t;
23         lf[t].x=x;lf[t].y=z;lf[t].z=y;
24         ++t;
25         lf[t].x=y;lf[t].y=z;lf[t].z=x;
26     }
27
28 }
29 void build_tu()
30 {
31     for(int i=1;i<=t;++i)
32       for(int j=1;j<i;++j)
33       {
34           if(lf[i].x<lf[j].x&&lf[i].y<lf[j].y)
35             G[i][j]=true;
36           if(lf[i].x<lf[j].y&&lf[i].y<lf[j].x)
37             G[i][j]=true;
38           if(lf[j].x<lf[i].x&&lf[j].y<lf[i].y)
39             G[j][i]=true;
40           if(lf[j].x<lf[i].y&&lf[j].y<lf[i].x)
41             G[j][i]=true;
42       }
43 }
44 int dp(int k)
45 {
46     if(d[k]>0) return d[k];
47     d[k]=lf[k].z;
48     for(int i=1;i<=t;++i)
49       if(G[k][i])  d[k]=max(d[k],dp(i)+lf[k].z);
50     return d[k];
51 }
52 int main()
53 {
54     int kase=0;
55     while(scanf("%d",&n)==1&&n)
56     {
57         ++kase;
58         input();
59         build_tu();
60         int ans=0;
61         for(int i=1;i<=t;++i)
62         {
63             ans=max(ans,dp(i));
64         }
65         printf("Case %d: maximum height = %d\n",kase,ans);
66     }
67     return 0;
68 }

UVA - 1347 Tour

 1 #include<cstring>
 2 #define N 1008
 3 #include<cmath>
 4 #include<iostream>
 5 using namespace std;
 6 #include<cstdio>
 7 int n;
 8 struct Zb{
 9   double x,y;
10 }zb[N];
11 double d[N][N]={0};
12 double dist(int a,int b)
13 {
14     return sqrt((zb[a].x-zb[b].x)*(zb[a].x-zb[b].x)+(zb[a].y-zb[b].y)*(zb[a].y-zb[b].y));
15 }
16 void input()
17 {
18     for(int i=1;i<=n;++i)
19       scanf("%lf%lf",&zb[i].x,&zb[i].y);
20 }
21 double dp(int i,int j)/*一开始误打成int,结果错了*/
22 {
23     if(d[i][j]>0)
24        return d[i][j];
25     if(i==n-1)
26       d[i][j]=dist(n-1,n)+dist(j,n);
27     else
28       d[i][j]=min(dp(i+1,j)+dist(i,i+1),dp(i+1,i)+dist(i+1,j));
29     return d[i][j];
30 }
31 int main()
32 {
33     while(scanf("%d",&n)==1)
34     {
35         input();
36         memset(d,0,sizeof(d));
37         dp(2,1);
38         printf("%0.2lf\n",d[2][1]+dist(1,2));
39     }
40     return 0;
41 }

UVA 12563

 1 /*一开始忘记把nex数组重置,后来发现输出少了一个‘\n’*/
 2 #include<iostream>
 3 using namespace std;
 4 #include<cstdio>
 5 #define N 55
 6 #define T 10000
 7 #include<cstring>
 8 int songg[N],f[T],kase,n,t,nex[T];
 9 int main()
10 {
11     scanf("%d",&kase);
12     int opt=0;
13     while(kase--)
14     {
15         opt++;
16         memset(songg,0,sizeof(songg));
17         memset(nex,0,sizeof(nex));
18         memset(f,0,sizeof(f));
19         scanf("%d%d",&n,&t);
20         for(int i=1;i<=n;++i)
21           scanf("%d",&songg[i]);
22         for(int i=1;i<=n;++i)
23         {
24           for(int j=t-1;j>=songg[i];--j)
25            {
26               if(f[j]<f[j-songg[i]]+1||(f[j]==f[j-songg[i]]+1&&nex[j]<nex[j-songg[i]]+songg[i]))
27               {
28                   nex[j]=nex[j-songg[i]]+songg[i];
29                   f[j]=f[j-songg[i]]+1;
30               }
31             }
32
33         }
34 /*注意题目要求的歌曲数目对优先,在这个基础上,然后时间尽量长,那么Dp转移的时候就要把两个条件都考虑到*/
35         /*int maxtim=0,maxnum=0;
36         for(int i=1;i<=t-1;++i)
37         {
38             if(f[i]+1>maxnum||(f[i]+1==maxnum&&maxtim<nex[i]+678))
39             {
40                 maxnum=f[i]+1;
41                 maxtim=nex[i]+678;
42             }
43         }*/
44         printf("Case %d: %d %d\n",opt,f[t-1]+1,nex[t-1]+678);
45     //    printf("Case %d: %d %d",opt,maxnum,maxtim);
46     //    if(kase)printf("\n");
47     }
48     return 0;
49 }
时间: 2024-10-13 22:44:29

《算法竞赛入门经典》动态规划复习的相关文章

《算法竞赛入门经典(第二版)》pdf

下载地址:网盘下载 内容简介  · · · · · · <算法竞赛入门经典(第2版)>是一本算法竞赛的入门与提高教材,把C/C++语言.算法和解题有机地结合在一起,淡化理论,注重学习方法和实践技巧.全书内容分为12 章,包括程序设计入门.循环结构程序设计.数组和字符串.函数和递归.C++与STL入门.数据结构基础.暴力求解法.高效算法设计.动态规划初步.数学概念与方法.图论模型与算法.高级专题等内容,覆盖了算法竞赛入门和提高所需的主要知识点,并含有大量例题和习题.书中的代码规范.简洁.易懂,不

算法竞赛入门经典+挑战编程+USACO

下面给出的题目共计560道,去掉重复的也有近500题,作为ACMer Training Step1,用1年到1年半年时间完成.打牢基础,厚积薄发.   一.UVaOJ http://uva.onlinejudge.org  西班牙Valladolid大学的程序在线评测系统,是历史最悠久.最著名的OJ.   二.<算法竞赛入门经典> 刘汝佳  (UVaOJ  351道题)  以下部分内容摘自:http://sdkdacm.5d6d.com/thread-6-1-1.html   "AO

(Step1-500题)UVaOJ+算法竞赛入门经典+挑战编程+USACO

下面给出的题目共计560道,去掉重复的也有近500题,作为ACMer Training Step1,用1年到1年半年时间完成.打牢基础,厚积薄发. 一.UVaOJ http://uva.onlinejudge.org 西班牙Valladolid大学的程序在线评测系统,是历史最悠久.最著名的OJ. 二.<算法竞赛入门经典> 刘汝佳  (UVaOJ  351道题)  以下部分内容摘自:http://sdkdacm.5d6d.com/thread-6-1-1.html “AOAPC I”是刘汝佳(大

《算法竞赛入门经典第二版》 P35 习题2-4 子序列的和(subsequence)

/* <算法竞赛入门经典第二版> P35 习题2-4: 输入两个正整数 n < m < 10^6,输出 (1/n)^2 + 1/(n+1)^2 +……+ 1/m^2,保留5位小数. 输入包含多组数据,结束标志为 m=n=0. 有错欢迎指出^_^ */ #include<stdio.h> int main() { int m,n,i,j=1; while(scanf("%d%d",&m,&n) != EOF) { double sum

算法竞赛入门经典_4.3_递归

看代码 #include <stdio.h> int f(int n){ return n == 0?1:f(n-1)*n; } int main() { printf("%d\n", f(5)); return 0; } 上面f函数使用了递归,递归由两部分组成,一是递归头,二是递归体. 我们使用gcc调试工具 H:\编程书籍学习\算法竞赛入门经典2代码\算法入门经典第四章>b f 'b' 不是内部或外部命令,也不是可运行的程序 或批处理文件. H:\编程书籍学习\算

算法竞赛入门经典训练指南

最近在看算法竞赛入门经典训练指南这本书,书中不错的算法我将在博客中发布,和大家共同学习. 题目: 在你的王国里有一条n个头的恶龙,你希望雇一些骑士把它杀死(即砍掉所有头).村里有m个骑士可以雇佣,一个能力值为m的骑士可以砍掉一个直径不超过x的头,且需要支付x个金币.如何雇佣骑士才能砍掉恶龙的所有头,且需要支付的金币最少?注意,一个骑士只能砍一个头(且不能被雇佣两次). 输入格式: 输入包含多组数据.每组数据的第一行为正整数m和n(1<=m,n<=20 000):以下m行每行为一个整数,即恶龙每

算法竞赛入门经典-训练指南(10881-Piotr&#39;s Ants)

题目大意: 一根长度为L的木棍一堆蚂蚁爬,向左或向右,速度都为1,若两蚂蚁碰撞则同时转头(转身时间忽略不计),问T时间之后每只蚂蚁的位置: 输入:t,(t个样例),每个样例输入 L,T,n,接下来是n行每行两个数据,一个POS(位置),一个dir(方向): 输出:按输入顺序输出每只蚂蚁的最终位置,若处于碰撞状态则输出Turning,掉下去输出"Fell off": 解题思路: 本题类似于<挑战程序设计>的一道水题(POJ -1852  Ants),思路题:不过本题输入并不一

棋盘覆盖问题(算法竞赛入门经典)

在一个 2^k * 2^k 个方格组成的棋盘中,若恰有一个方格与其它方格不同,则称该方格为一特殊方格,称该棋盘为一特殊棋盘.显然特殊方格在棋盘上出现的位置有 4^k 种情形.因而对任何 k>=0 ,有 4^k 种不同的特殊棋盘.下图所示的特殊棋盘为 k=2 时 16 个特殊棋盘中的一个. 在棋盘覆盖问题中,要用下图中 4 中不同形态的 L 型骨牌覆盖一个给定的特殊棋牌上除特殊方格以外的所有方格,且任何 2 个 L 型骨牌不得重叠覆盖.易知,在任何一个 2^k * 2^k 的棋盘中,用到的 L 型

【算法竞赛入门经典】【第三章】课后习题(第二部分)

自从蓝桥杯之后,都没写博客了.今天将之前第三章还差的一部分习题答案补上. 3-4整数相加 这一题题目有提示,说选择合适的输入方式,即可简化问题.刚开始没想到cin,结果还用字符串来做,多亏别人提醒我一下,我才想起cin.惭愧啊.. #include <iostream> using namespace std; int main() { int a,b; char op; while(cin>>a>>op>>b){ switch(op){ case '+':