动态规划POJ专题

声明:本文属博主原创文章,未经允许请勿转载。

 

经典题目题号(此处为转载):
容易: 
1018, 1050, 1083, 1088, 1125, 1143, 1157, 1163, 1178, 1179, 1189, 1191,1208, 1276, 1322, 1414, 1456, 1458, 

1609, 1644, 1664, 1690, 1699, 1740, 1742, 1887, 19261936, 1952, 1953, 1958, 1959, 1962, 1975, 1989, 2018, 

2029, 2039, 2063, 2081, 2082, 2181, 2184, 2192, 2231, 2279, 2329, 2336, 2346, 2353, 2355, 2356, 2385, 2392, 2424, 
不易: 
1019, 1037, 1080, 1112, 1141, 1170, 1192, 1239, 1655, 1695, 1707, 1733(区间减法加并查集)

1737, 1837, 1850, 1920(加强版汉罗塔), 1934(全部最长公共子序列), 1964(最大矩形面积,O(n*m)算法), 2138, 2151, 2161, 2178, 
推荐: 
1015, 1635, 1636(挺好的), 1671, 1682, 1692(优化), 1704, 1717, 1722, 1726, 1732, 1770, 

1821, 1853, 1949, 2019, 2127, 2176, 2228, 2287, 2342, 2374, 2378, 2384, 2411 

 

1.POJ 1050 To the Max

【算法分析】最大连续子段和的拓展,枚举行起点与终点,将起点行、终点行中间的数组成的矩阵每列求和,可压缩成一个一维数组,然后分别求最大连续子段和,输出最大答案即可。

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 int a[110][110],mat[110],n,ans=-1e8;
 5 int dp(){
 6     int dp[110],t=-1e8;
 7     memset(dp,0,sizeof(dp));
 8     dp[1]=mat[1];
 9     for (int i=2;i<=n;i++)
10     if (dp[i-1]<0) dp[i]=mat[i];
11     else dp[i]=dp[i-1]+mat[i];
12     for (int i=1;i<=n;i++)
13     if (dp[i]>t) t=dp[i];
14     return t;
15 }
16 int main(){
17     scanf("%d",&n);
18     for (int i=1;i<=n;i++)
19     for (int j=1;j<=n;j++) scanf("%d",&a[i][j]);
20     for (int i=1;i<=n;i++)
21     for (int j=i;j<=n;j++){
22         memset(mat,0,sizeof(mat));
23         for (int k=1;k<=n;k++)
24         for (int l=i;l<=j;l++)
25             mat[k]+=a[l][k];
26         int t=dp();
27         if (ans<t) ans=t;
28     }
29     printf("%d",ans);
30     return 0;
31 }
View Code

 2.POJ 1088 滑雪

【算法分析】最大上升子序列的二维拓展,用DP+递归求出四个方向的最大序列长度,输出最大答案即可。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 int plus[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
 6 int r,c,map[110][110],len[110][110],ans=0;
 7 int dp(int x,int y){
 8     if (len[x][y]) return len[x][y];
 9     int maxans=0,s;
10     for (int t=0;t<4;t++){
11         int i=x+plus[t][0],j=y+plus[t][1];
12         if (i&&j&&i<=r&&j<=c&&map[i][j]<map[x][y]){
13             s=dp(i,j);
14             if (s>maxans) maxans=s;
15         }
16     }
17     len[x][y]=maxans+1;
18     return len[x][y];
19 }
20 int main(){
21     scanf("%d%d",&r,&c);
22     memset(len,0,sizeof(len));
23     for (int i=1;i<=r;i++)
24     for (int j=1;j<=c;j++)
25         scanf("%d",&map[i][j]);
26     for (int i=1;i<=r;i++)
27     for (int j=1;j<=c;j++){
28         len[i][j]=dp(i,j);
29         if (len[i][j]>ans) ans=len[i][j];
30     }
31     printf("%d",ans);
32     return 0;
33 }
View Code

 

 

转载于:https://www.cnblogs.com/Double680/p/5485998.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值