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);}


单调栈AC代码如下:

//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;}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 一岁宝宝没耐心怎么办 孩子挑食 幼儿园老师该怎么办 小孩被惯的无法无天怎么办 高中的儿子不写作业怎么办 儿子总是不写作业怎么办 长鸡眼脚背肿了怎么办 脚上反复长鸡眼怎么办 脚底长鸡眼很痒怎么办 小脚趾上长鸡眼怎么办 6岁宝宝不爱学习怎么办 上班站久了腿肿怎么办 站时间长了腿肿怎么办 孩子做作业老是粗心大意怎么办 高中孩子没学习兴趣怎么办 初三孩子失去学习兴趣怎么办 初二对学习兴趣不大怎么办 脸上痒发红发肿怎么办 孩子作业拖拉爱丢三落四怎么办 腿肌肉按摩肿了怎么办 孩子上一年级成绩差怎么办 小孩脖子拧筋了怎么办 小孩塑料玩具拧不出来怎么办 一年级孩子做数学题粗心怎么办 手和脚有点肿怎么办 手破了之后肿了怎么办 手指肿了有脓怎么办 宝宝手指红肿有脓怎么办 孩子一听做作业就烦气怎么办 虎皮鹦鹉脚瘸了怎么办 虎皮鹦鹉脚受伤了怎么办 虎皮鹦鹉脚流血了怎么办 虎皮鹦鹉被风扇打到脚怎么办 虎皮鹦鹉脚脱臼了怎么办 孩子作业做得慢怎么办 员工给公司造成损失怎么办 小孩有写不完的作业家长怎么办 一年级孩子作业太粗心怎么办 孩子最近不好好做作业怎么办 工作压力大害怕做不好怎么办 孩子的数算不对怎么办? 孩子计算老是出错怎么办呢