声明:本文属博主原创文章,未经允许请勿转载。
经典题目题号(此处为转载):
容易:
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, 1926, 1936, 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 }
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 }