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;
    }
    
  • 相关阅读:
    C语言中变量和函数类型
    ubuntu中耳机声音小的解决方案
    数据结构学习4——栈
    Linux 引导过程内幕
    linux gdb 没有符号表被读取。请使用 "file" 命令。
    linux 内存泄漏检查工具
    数据结构学习5——队列
    [转载]Ubuntu垃圾清理
    系统消息
    窗口相关概念和对应关系
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/15136266.html
Copyright © 2011-2022 走看看