hdu 1505 1506 2870 dp小礼包
来源:互联网 发布:cbox正在解析直播数据 编辑:程序博客网 时间:2024/04/27 16:14
1505
思路:
读入的时候先处理一下,使得 map[i][j] 记录的是 第 i 行中 连续到第 j 列有多少个 F.
就样例而言
R F F F F F
F F F F F F
R R R F F F
F F F F F F
F F F F F F
可以被处理为
0 1 2 3 4 5
1 2 3 4 5 6
0 0 0 1 2 3
1 2 3 4 5 6
1 2 3 4 5 6
对于任意一个 map[i][j],我们如果要找到包含该点在内的最大的面积的话,只要关注这一列的状况,因为 map[i][j] 本身就记录了该行的状况。
从 第i行 开始向上找,map[i-k][j] 的最小值就代表了从 第j列开始可以向左拓展的最大宽度(类似木桶原理(?),再乘上向上找的行数,就是一块矩形的面积了,然后所有这些面积里面取最大值,就是答案。
另外考虑到可能有很多0,那么我们向上一旦找到一个0,就可以停了,显然以后的最小值都会是0,乘出来也都会是0。从图形上理解,这代表着从 map[i-k][j] 那点开始是不能够连续到该点的,更不用说向上了。
以样例的最后一行(i=6)为例
j=1时,1*1,1*2 最大值为2
j=2时,2*1,2*2 最大值为4
j=3时,3*1,3*2 最大值为6
j=4时,4*1,4*2,1*3,1*4,1*5 最大值为8
j=5时,5*1,5*2,2*3,2*4,2*5 最大值为10
j=6时,6*1,6*2,3*3,3*4,3*5 最大值为15
(上面的式子都是宽度乘高度)
后来看discuss的时候看到一种很棒的做法,后面再讲。
(其实这段代码我写的一点也不像dp)
AC代码如下:
//1505.cpp#include <iostream>#include <string>#define maxn 1010int map[maxn][maxn],minim[maxn][maxn];using namespace std;int main(){int T,m,n,i,j,ans,k,x,anss;string s;char ch;cin >> T;while (T--){cin >> m >> n;for (i=1;i<=m;++i)for (j=1;j<=n;++j){ cin >> ch;if (ch=='F') map[i][j] = map[i][j-1]+1;elsemap[i][j] = 0;}anss = 0;for (i=1;i<=m;++i)for (j=1;j<=n;++j){x = ans = map[i][j];for (k=1;k<=i-1;++k){if (map[i-k][j]==0)break;x = min(x,map[i-k][j]);ans = max(ans,x*(k+1));}anss = max(anss,ans);}cout << anss*3 << endl;getline(cin,s);}return 0;}
discuss里面有一种做法,点击打开链接,是先预处理好l,r,h数组。
其中一个很棒的想法是,对于l数组,每次和左边比较的时候,不需要一个一个比过去,因为如果 h[i-1]>=h[i] 就这样去判断 l[i-1] 所指的位置的前一个位置是不是满足这个条件然后一直往前找,这样大大减少了循环次数。
1506
其实和1505一样的道理,只是换成了一维的
但是要注意 long long
看discuss里面学到了很棒的几个做法
一个是分治,用了栈,点击打开链接
另一个是单调栈做法,感觉学习到了很多,单调栈相关
分治AC代码如下:
//1506.cpp#include <iostream>#include <stack>#define maxn 100010long long a[maxn];using namespace std;long long maxi(long long l,long long r);int main(){//freopen("1506.in","r",stdin);//freopen("1506.out","w",stdout);long long n,i;while (cin >> n && n){for (i=0;i<n;++i)cin >> a[i];cout << maxi(0,n-1) << endl;}//fclose(stdin);//fclose(stdout);return 0;}long long maxi(long long l,long long r){if (r-l==1)return max(max(a[r],a[l]),min(a[r],a[l])*2);if (r==l)return a[l];//cout << l << " " << r << endl;stack<long long> left,right;long long i,j,low,len,ans;long long mid = (l+r) >> 1;long long maxl = maxi(l,mid);//cout << l << " " << r << " " << maxl << endl;long long maxr = maxi(mid+1,r);//cout << l << " " << r << " " << maxr << endl;for (i=l;i<=mid;++i)left.push(a[i]);for (i=r;i>mid;--i)right.push(a[i]);low = INT_MAX;len = ans = 0;while (!left.empty() || !right.empty()){if (!left.empty() && left.top()>=low){++ len;ans = max(ans,low*len);left.pop();}else if (!right.empty() && right.top()>=low){++ len;ans = max(ans,low*len);right.pop();}else if (!left.empty() && !right.empty()){if (left.top() <= right.top()){++ len;low = right.top();ans = max(ans,low*len);right.pop();}else{++ len;low = left.top();ans = max(ans,low*len);left.pop();}}else if (!left.empty()){++ len;low = min(low,left.top());ans = max(ans,len*low);left.pop();}else if (!right.empty()){++ len;low = min(low,right.top());ans = max(ans,len*low);right.pop();}}//cout << l << " " << r << " " << max(max(maxl,maxr),ans) << endl;return max(max(maxl,maxr),ans);}
//1506.cpp#include <iostream>#include <cstdio>#include <stack>using namespace std;stack<long long> l,r;#define maxn 100010long long le[maxn],ri[maxn],a[maxn];int main(){//freopen("1506.in","r",stdin);//freopen("15062.out","w",stdout);long long n,i,ans,x;while (cin >> n && n){while (!l.empty())l.pop();while (!r.empty())r.pop();for (i=0;i<n;++i)cin >> a[i];l.push(0);le[0] = 0;r.push(n-1);ri[n-1] = n-1;for (i=1;i<n;++i){if (a[l.top()] >= a[i]){while (!l.empty() && a[l.top()] >= a[i]){x = l.top();l.pop();}le[i] = le[x];}elsele[i] = i;l.push(i);}//for (i=0;i<n;++i)//cout << le[i] << " ";//cout << endl;for (i=n-2;i>=0;--i){if (a[r.top()] >= a[i]){while (!r.empty() && a[r.top()] >= a[i]){x = r.top();r.pop();}ri[i] = ri[x];}elseri[i] = i;r.push(i);}//for (i=0;i<n;++i)//cout << ri[i] << " ";ans = 0;for (i=0;i<n;++i)ans = max(ans,(ri[i]-le[i]+1)*a[i]);cout << ans << endl;}//fclose(stdin);//fclose(stdout);return 0;}
2870
其实就是做了三遍1505,分别对 a,b,c 的状态进行记录
AC代码如下:
//2870.cpp#include <iostream>using namespace std;#define maxn 1010#include <cstring>struct tri{short a,b,c;};tri h[maxn][maxn],l[maxn][maxn],r[maxn][maxn];char c[maxn][maxn];int main(){//freopen("2870.in","r",stdin);//freopen("2870.out","w",stdout);int m,n,i,j,k,ans;while (cin >> m >> n){memset(h,0,sizeof(h));for (i=1;i<=m;++i)for (j=1;j<=n;++j){cin >> c[i][j];if (c[i][j] == 'a' || c[i][j] == 'w' || c[i][j] == 'y' || c[i][j] == 'z')h[i][j].a = h[i-1][j].a + 1;if (c[i][j] == 'b' || c[i][j] == 'w' || c[i][j] == 'x' || c[i][j] == 'z')h[i][j].b = h[i-1][j].b + 1;if (c[i][j] == 'c' || c[i][j] == 'x' || c[i][j] == 'y' || c[i][j] == 'z')h[i][j].c = h[i-1][j].c + 1;}for (i=1;i<=m;++i)for (j=1;j<=n;++j){if (h[i][j].a){k = j;while (h[i][k-1].a >= h[i][j].a && (c[i][k-1] == 'a' || c[i][k-1] == 'w' || c[i][k-1] == 'y' || c[i][k-1] == 'z'))-- k;l[i][j].a = k;}if (h[i][j].b){k = j;while (h[i][k-1].b >= h[i][j].b && (c[i][k-1] == 'b' || c[i][k-1] == 'w' || c[i][k-1] == 'x' || c[i][k-1] == 'z'))-- k;l[i][j].b = k;}if (h[i][j].c){k = j;while (h[i][k-1].c >= h[i][j].c && (c[i][k-1] == 'c' || c[i][k-1] == 'x' || c[i][k-1] == 'y' || c[i][k-1] == 'z'))-- k;l[i][j].c = k;}}for (i=1;i<=m;++i)for (j=1;j<=n;++j){if (h[i][j].a){k = j;while (h[i][k+1].a >= h[i][j].a && (c[i][k+1] == 'a' || c[i][k+1] == 'w' || c[i][k+1] == 'y' || c[i][k+1] == 'z'))++ k;r[i][j].a = k;}if (h[i][j].b){k = j;while (h[i][k+1].b >= h[i][j].b && (c[i][k+1] == 'b' || c[i][k+1] == 'w' || c[i][k+1] == 'x' || c[i][k+1] == 'z'))++ k;r[i][j].b = k;}if (h[i][j].c){k = j;while (h[i][k+1].c >= h[i][j].c && (c[i][k+1] == 'c' || c[i][k+1] == 'x' || c[i][k+1] == 'y' || c[i][k+1] == 'z'))++ k;r[i][j].c = k;}}ans = 0;for (i=1;i<=m;++i)for (j=1;j<=n;++j){if (l[i][j].a)ans = max(ans,(r[i][j].a-l[i][j].a+1) * h[i][j].a);if (l[i][j].b)ans = max(ans,(r[i][j].b-l[i][j].b+1) * h[i][j].b);if (l[i][j].c)ans = max(ans,(r[i][j].c-l[i][j].c+1) * h[i][j].c);}cout << ans << endl;}//fclose(stdin);//fclose(stdout);return 0;}
- hdu 1505 1506 2870 dp小礼包
- HDU 1506 && HDU1505 && HDU 2870 (DP).
- HDU 1506 1505 2870 2830一类DP的总结
- HDU 1505 1506 2830 2870求最大矩阵面积 DP
- HDU 1421 搬寝室 (dp+小贪心)
- hdu 3709 数位dp(小思维)
- HDU 5735 Born Slippy 【DP + 小技巧】
- HDU 4734 数位DP 小水
- 每日礼包
- hdu 2870 dp
- hdu 2870 DP
- HDU 2870 dp
- HDU 1505 dp
- hdu 1505 #DP
- hdu 1505 DP
- hdu 1505 dp
- hdu 1505 dp
- hdu 1505(矩阵dp)
- c!!#获取系!!!统启!!!!动!后经!过的时!!!!间
- iscsi用gfs2文件系统实现磁盘共享
- python学习笔记一
- 349. Intersection of Two Arrays
- 233 Matrix hdu 5015(矩阵快速幂)
- hdu 1505 1506 2870 dp小礼包
- ubuntu16.04+Cuda8.0+CuDnn v5+OpenCV3.1.0+Matlab2014+Python+Caffe安装
- (9)金融资产的计量
- 【Android 基础】SnackBar详解
- Context Switch Definition
- ScrollView起始位置不是最顶部的解决办法
- LNMP一键安装详解
- Activity之间利用Intent进行数据的传递
- ObjcRuntimeGuide笔记