《算法竞赛入门经典》动态规划复习
Posted tech-chen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《算法竞赛入门经典》动态规划复习相关的知识,希望对你有一定的参考价值。
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种不同的面值
第2行s
第3到n+2行为n种不同的面值
输出格式
第1行为最小值
第2行为最大值
第2行为最大值
测试样例1
输入
3
6
1
2
3
输出
2
6
备注
1<=n<=100
1<=s<=10000
1<=a[i]<=s
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 }
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 }
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 }
以上是关于《算法竞赛入门经典》动态规划复习的主要内容,如果未能解决你的问题,请参考以下文章