zoukankan      html  css  js  c++  java
  • 洛谷 P1950 长方形(单调栈,dp)

    传送门


    解题思路

    单调栈的一道好题。
    枚举矩阵右下角的端点。
    首先可以发现,对于一个确定的右下角,对矩阵有限制的*的位置的行数是从左到右严格递增的。
    也就是这个样子:
    image
    所有就可以用单调栈储存一下这个对答案有影响的1的位置。
    于是我们就有了状态转移方程:

    [dp[i][j]=dp[i][s.top()]+(i-a[j])*(j-s.top()) ]

    其中 (a[j]) 表示第 (j) 列最靠下的 (1) 的行数。
    如何理解?就是从s.top()那一列转移过来,所以s.top()那一列的方案数再加上新的矩形的方案数。
    dp第一维i可以省略掉。
    最后答案就是所有dp累加起来。

    AC代码

    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<queue>
    #include<set>
    #include<map>
    #include<vector>
    #include<iomanip>
    #include<ctime>
    #include<stack>
    using namespace std;
    const int maxn=1005;
    int n,m,a[maxn],ans[maxn];
    long long anss;
    int main()
    {
        ios::sync_with_stdio(false);
        cin>>n>>m;
        for(int i=1;i<=n;i++){
        	stack<int> s;
        	for(int j=1;j<=m;j++){
        		char c;
        		cin>>c;
        		if(c=='*') a[j]=i;
        		while(!s.empty()&&a[s.top()]<=a[j]) s.pop();
        		if(!s.empty()) ans[j]=ans[s.top()]+(i-a[j])*(j-s.top());
        		else ans[j]=(i-a[j])*j;
        		s.push(j);
        		anss+=ans[j];
    		}
    	}
    	cout<<anss;
        return 0;
    }
    
  • 相关阅读:
    捕捉整个桌面的图片
    在Image控件中绘制文字
    绘图
    Image1.Canvas画图笔刷
    将图片序列保存为GIF文件
    拷贝剪贴板图像到窗体
    显示 png 图片
    将图片以字符串方式保存
    复制图片的一部分
    反转字符串
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/15136266.html
Copyright © 2011-2022 走看看