F.
把2*n个人分成 两个人数相等的队伍,每两个人之间都有一个竞争值,当分成两个队伍后,两个队伍之间的竞争值之和最大为多少
做法: 对每个人进行搜索将它放在a或b队里,每放一个人就计算一下当前的竞争值,这样往后搜索的时候就可以利用一下前面的竞争值,避免重复计算,(还有一个小优化,可以把第一个人固定放在第一个队伍里,可以减少一半的状态空间)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n;
ll c[30][30];
vector<int>a;
vector<int>b;
ll ans=0;
void dfs(ll now, ll pa, ll pb, ll sum)
{
if(now==n*2+1)
{
ans=max(ans,sum);
return ;
}
if(pa<n)
{
ll add=0;
for(int i=0;i<b.size();i++)
{
add+=c[now][b[i]];
}
a.push_back(now);
dfs(now+1,pa+1,pb,sum+add);
a.pop_back();
}
if(pb<n)
{
ll add=0;
for(int i=0;i<a.size();i++)
{
add+=c[now][a[i]];
}
b.push_back(now);
dfs(now+1,pa,pb+1,sum+add);
b.pop_back();
}
}
int main()
{
cin>>n;
for(int i=1;i<=n*2;i++)
{
for(int j=1;j<=n*2;j++)
{
scanf("%lld",&c[i][j]);
}
}
a.push_back(1);
dfs(2,1,0,0);
cout<<ans<<endl;
return 0;
}
H.
题意:给你一个N*M的01矩阵,求第二大的全为1的长方形的面积
题解:把每一行当做长方形的底边,O(N*M)预处理出每个以1为宽,高为h的全1 长方形,然后对每个底边使用单调栈求出最大的全1长方形的面积(x*y) 再把(x-1)*y 和x*(y-1) 和x*y 放入一个只维护最大两个元素的multiset,最后的答案就是multiset里第二大的元素。
几个注意点:
1.预处理计算高度的时,只有连续的1才能被计算进去,不连续的1以0处理。
2.初始指针p指向0,高度s[p]=-1(目的不让指针越界,如果你的入栈条件是当前指针指向的元素<要入栈的元素, 最好条件改成当前指针的元素<=要入栈的元素,可以避免这个问题)
3.每条底边最后再额外增加一个高度为0宽度为1的长方形,(使栈中的全部长方形能够出栈更新)
4.ans的更新条件为 累计宽度we*当前高度s[p]>=ans,此时需要更新multiset,防止一条底边中有多个面积相同的长方形而只计算了一次。
#include<bits/stdc++.h>
using namespace std;
int n,m;
int mp[1003][1003];
char sp[1003][1003];
int h[1003][1003];
multiset<int>q;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
scanf("%s",sp[i]+1);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
mp[i][j]=sp[i][j]-'0';
if(h[i-1][j])
{
if(mp[i][j])h[i][j]=h[i-1][j]+mp[i][j];
else h[i][j]=0;
}
else h[i][j]=mp[i][j];
}
}
for(int i=1;i<=n;i++)
{
int ans=-1;
int p=0;
int s[1003];
int w[1003];
int x,y;
s[p]=-1;
w[p]=0;
for(int j=1;j<=m+1;j++)
{
if(s[p]<h[i][j])
{
s[++p]=h[i][j],w[p]=1;
}
else
{
int we=0;
while(p!=-1)
{
if(s[p]<h[i][j])
{
s[++p]=h[i][j];
w[p]=we+1;
break;
}
else
{
we+=w[p];
if(we*s[p]>=ans)
{
ans=s[p]*we;
x=we;
y=s[p];
q.insert(x*(y-1));
q.insert(y*(x-1));
q.insert(x*y);
}
p--;
}
}
}
}
while(q.size()>2)
{
q.erase(q.begin());
}
}
cout<<(*q.begin())<<endl;
return 0;
}