首页 > 代码库 > 《算法竞赛入门经典》动态规划复习

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

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 }

 

                 

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