2019牛客暑期多校训练营(第二场合集)

H-Second Large Rectangle

题意:

输入一个n*m的矩阵,矩阵由字符0和1组成,需要你找到第二大的全为1的矩阵的大小

分析:

将n*m的矩阵转化为n个以i为底的直方图,利用单调栈分别对每个直方图进行求解,找出次大值

前置知识:单调栈、相似习题:POJ 2559  POJ3494(题解

代码:

#include<iostream>
#include<cstdio>
#include<stack>
using namespace std;
const int MAX=1009;
int n,m;
int max1,max2;
char ch[MAX][MAX];
int cnt[MAX][MAX];
struct node{
    int height,left;
    node(){}
    node(int a,int b){
        height=a,left=b;
    }
};
stack<node>st;
void check(int x)
{
    if(x>max1){
        max2=max1;
        max1=x;
    }
    else if(x>max2)
        max2=x;
}
int main()
{
    max1=0,max2=0;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%s",ch[i]+1);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(ch[i][j]=='1')
                cnt[i][j]=cnt[i-1][j]+1;
    
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            int p=j;
            while(!st.empty()&&st.top().height > cnt[i][j])
            {
                check(st.top().height*(j-st.top().left));
                check((st.top().height-1)*(j-st.top().left));
                check(st.top().height*(j-st.top().left-1));
                //cout<<"**"<<j<<' '<<st.top().left<<endl;
                p=min(p,st.top().left);
                 
                st.pop();
            }
            p=min(p,j);
        //    cout<<cnt[i][j]<<' '<<p<<endl;
            st.push(node(cnt[i][j],p));
        }
        while(!st.empty())
        {
            check(st.top().height*(m+1-st.top().left));
            check((st.top().height-1)*(m+1-st.top().left));
            check(st.top().height*(m+1-st.top().left-1));
            st.pop();
        }
    }
    cout<<max2<<endl;
    return 0;
}
View Code

 

F-Partition problem

题意:

将2N个人分成均为N的两队人,一队的人i对另一队的每个人都存在一个贡献vi,j,求贡献和最大

分析:

直接暴力搜索每种情况即可QAQ

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int MAX=40;
int val[MAX][MAX],t1[MAX],t2[MAX];
int n;
ll ans;
void dfs(int pos,int cnt1,int cnt2,ll sum)
{
    if(cnt1==cnt2&&cnt1==n)
    {
        ans=max(ans,sum);   //取最大值
        return;
    }
    ll temp=0;
    if(cnt1<n)     //下一个人插入到一队
    {
        for(int i=0;i<cnt2;i++)
            temp+=val[pos][t2[i]];
        t1[cnt1]=pos;
        dfs(pos+1,cnt1+1,cnt2,sum+temp);
    }
    temp=0;
    if(cnt2<n)   //插入到二队
    {
        for(int i=0;i<cnt1;i++)
            temp+=val[t1[i]][pos];
        t2[cnt2]=pos;
        dfs(pos+1,cnt1,cnt2+1,sum+temp);
    }
}
int main()
{
    ans=0;
    scanf("%d",&n);
    for(int i=0;i<2*n;i++)
        for(int j=0;j<2*n;j++)
            scanf("%d",&val[i][j]);
    dfs(0,0,0,0);
    printf("%lld\n",ans);
    return 0;
}
View Code

 

posted @ 2019-07-30 20:23  _Carrot  阅读(131)  评论(0编辑  收藏  举报