2019牛客暑假多校赛第二场 F和G

F-Partition problem

https://ac.nowcoder.com/acm/contest/882/F

题意:输入一个数n,代表总共有2n个人,然后每个人对所有人有个贡献值,然后问题需要将2n个人分成两组,每组n个人,问如何分组使得两组之间的价值最大,同组人不算价值。

思路:直接dfs暴力分组。

//aeha
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
const int inf = 0x3f3f3f3f;
int dir[8][2]={{1,0},{0,1},{1,1},{1,-1},{-1,1},{-1,-1},{0,-1},{-1,0}};
#define pi acos(-1)
#define ls rt<<1
#define rs rt<<1|1
#define me0(s) memset(s,0,sizeof(s))
#define me1(s) memset(s,1,sizeof(s))
#define mef(s) memset(s,-1,sizeof(s))
#define meinf(s) memset(s,inf,sizeof(s))
const int N=105;
ll ans;
int n;
int t1[30],t2[30];
int a[N],b[N],v[N][N];
inline int read() {
    char c=getchar(); int x=0, f=1;
    while(c<'0'|c>'9') {if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    return x*f;
}
ll q_pow(ll a,ll b,ll mod){
    ll anss=1;
    while(b){
        if(b&1) anss=anss*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return anss;
}
ll q_mul(ll a,ll b,ll mod){
    ll anss=0;
    while(b){
        if(b&1) anss=(anss+a)%mod;
        a=(a+a)%mod;
        b>>=1;
    }
    return anss;
}
void dfs(int pos,int cnt1,int cnt2,ll ret){
// pos表示当前搜的人的序号,cnt1表示第一组的人数,cnt2表示第二组的人数,ret表示贡献
    if(cnt1==cnt2&&cnt1==n){
        ans=max(ans,ret);
        return ;
    }
    ll tmp=0;
    if(cnt1<n){
        for(int i=0;i<cnt2;i++){
            tmp+=v[pos][t2[i]];
        }
        t1[cnt1]=pos;
        dfs(pos+1,cnt1+1,cnt2,ret+tmp);
    }
    tmp=0;
    if(cnt2<n){
        for(int i=0;i<cnt1;i++){
            tmp+=v[pos][t1[i]];
        }
        t2[cnt2]=pos;
        dfs(pos+1,cnt1,cnt2+1,ret+tmp);
    }
}
int main(int argc, char * argv[]) 
{
    std::ios::sync_with_stdio(false);
    cin>>n;
    ans=0;
    for(int i=0;i<2*n;i++){
        for(int j=0;j<2*n;j++){
            cin>>v[i][j];
        }
    }
    dfs(0,0,0,0);
    cout<<ans<<endl;
    return 0;
}

H-Second Large Rectangle

https://ac.nowcoder.com/acm/contest/882/H

题意:给定一个n*m的矩阵,其中全由0,1两个数字组成,问找到的第二大的全由1组成的矩阵的面积是多少。

思路:先用单调栈的求第一大矩阵的模板,然后在后面的时候修改一下 ,将各种状态保存下来,注意去重。然后输出第二大的面积就行。

#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
const int inf = 0x3f3f3f3f;
#define pi acos(-1)
#define ls rt<<1
#define rs rt<<1|1
#define me0(s) memset(s,0,sizeof(s))
#define me1(s) memset(s,1,sizeof(s))
#define mef(s) memset(s,-1,sizeof(s))
#define meinf(s) memset(s,inf,sizeof(s))
const int N=1005;
char a[2060][2060];
int h[2060];
int L[2060],R[2060];
map<int,int> ma;
bool v[1005][1005];
inline int read() {
    char c=getchar(); int x=0, f=1;
    while(c<'0'|c>'9') {if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    return x*f;
}
ll q_pow(ll a,ll b,ll mod){
    ll anss=1;
    while(b){
        if(b&1) anss=anss*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return anss;
}
ll q_mul(ll a,ll b,ll mod){
    ll anss=0;
    while(b){
        if(b&1) anss=(anss+a)%mod;
        a=(a+a)%mod;
        b>>=1;
    }
    return anss;
}
int main(int argc, char * argv[]) 
{
    std::ios::sync_with_stdio(false);
    int n,m;
    while(cin>>n>>m){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                cin>>a[i][j];
            }
        }
        int maxn=0;
        for(int i=1;i<=n;i++){
            me0(v);
            for(int j=1;j<=m;j++){
                if(a[i][j]=='1')
                    h[j]++;
                else h[j]=0;
            }
            h[0]=h[m+1]=-1;
            stack<int>s;
            for(int j=1;j<=m;j++){
                L[j]=0;
                if(s.size()==0){
                    s.push(j);
                    L[j]=j;
                }
                else{
                    while(s.size()>0&&h[s.top()]>=h[j])
                        s.pop();
                    if(s.size()==0) L[j]=1;
                    else L[j]=s.top()+1;
                    s.push(j);
                }
            }
            while(!s.empty()){
                s.pop();
            }
            for(int j=m;j>=1;j--){
                R[j]=m;
                if(s.size()==0){
                    s.push(j);R[j]=j;
                }
                else{
                    while(s.size()>0&&h[s.top()]>=h[j])s.pop();
                    if(s.size()==0)R[j]=m;
                    else R[j]=s.top()-1;
                    s.push(j);
                }
            }
            for(int j=1;j<=m;j++){
            if(!v[L[j]][R[j]]){
                    ma[h[j]*(R[j]-L[j]+1)]++;
                    v[L[j]][R[j]]=1;
                    ma[h[j]*(R[j]-L[j])]++;
                    ma[(h[j]-1)*(R[j]-L[j]+1)]++;
                }
                if(h[j]*(R[j]-L[j]+1)>maxn)
                    maxn=h[j]*(R[j]-L[j]+1);
            }
        }
           int flag=0,ans,pos;
        for(int i=maxn;i>=0;i--){
            if(ma[i]&&ma[i]>1){
                ans=i;
                flag=1;
                break;            
            }
            else if(ma[i]&&ma[i]==1){
                pos=i;
                break;
            }
        }
        if(flag) cout<<ans<<endl;
        else{
            for(int i=pos-1;i>=0;i--){
                if(ma[i]){
                    ans=i;
                    break;
                }
            }
            cout<<ans<<endl;
        } 
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wushengyang/p/11224403.html