F、https://ac.nowcoder.com/acm/contest/882/F
題意:有2N個人,分成兩組,每組N個。使得不同組間的人的競賽值之和最大。
解法之一:暴搜!!。時限4S,感覺就是明顯暗示這是要暴力搜的題。(再次溫習DFS)(枚舉長度為N的子集,保存結果的最大)。
#include <bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
typedef long long ll;
int N;
ll a[50][50];
ll res=-1;
ll v1[50],v2[50];
void dfs(ll sum,int x,int cnt1,int cnt2)
{
if(cnt1==N){
ll tmp=sum;
for(int i=x;i<=2*N;i++){
for(int j=1;j<=cnt1;j++){
tmp+=a[i][v1[j]];
}
}
res=max(res,tmp);
return ;
}
if(cnt2==N){
ll tmp=sum;
for(int i=x;i<=2*N;i++){
for(int j=1;j<=cnt2;j++){
tmp+=a[i][v2[j]];
}
}
res=max(res,tmp);
return ;
}
ll tmp=sum;
v1[++cnt1]=x;
for(int i=1;i<=cnt2;i++){
tmp+=a[v2[i]][x];
}
dfs(tmp,x+1,cnt1,cnt2);
cnt1--;
tmp=sum;
v2[++cnt2]=x;
for(int i=1;i<=cnt1;i++){
tmp+=a[v1[i]][x];
}
dfs(tmp,x+1,cnt1,cnt2);
cnt2--;
}
int main()
{
scanf("%d",&N);
for(int i=1;i<=2*N;i++){
for(int j=1;j<=2*N;j++){
scanf("%lld",&a[i][j]);
}
}
dfs(0,1,0,0);
printf("%lld\n",res);
return 0;
}
H、https://ac.nowcoder.com/acm/contest/882/H
題意:給一個大小為N*M的01矩陣,求這個矩陣裏的第二大01矩陣(全1)。
解法之一:在求最大01矩陣的做法的基礎上修改,求最大的做法是:先每個1都預處理這個點所能到達向上的最大高度,再用單調棧維護每個1所能到達的最左最右的點的坐標。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int n,m;
char mp[2010][2010];
int pre[2010][2010];
int l[2010],r[2010];
stack<int>s;
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%s",mp[i]+1);
for(int j=1;j<=m;j++)
{
if(mp[i][j]=='0')
pre[i][j]=0;
else
pre[i][j]=pre[i-1][j]+1;
}
}
int max1=-1;
int max2=-1;
int fl,fr,fi;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
while(!s.empty()&&pre[i][j]<=pre[i][s.top()]) s.pop();
l[j]=s.size()==0?1:s.top()+1;
s.push(j);
}
while(!s.empty()) s.pop();
for(int j=m;j>=1;j--)
{
while(!s.empty()&&pre[i][j]<=pre[i][s.top()])
s.pop();
r[j]=s.size()==0?m:s.top()-1;
s.push(j);
}
while(!s.empty()) s.pop();
for(int j=1;j<=m;j++)
{
int now=pre[i][j]*(r[j]-l[j]+1);
if(now>max1){
max1=now;
fl=l[j],fr=r[j],fi=i;
}
}
}
int ppp=fr-fl+1;
int yyy=max1/ppp;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
while(!s.empty()&&pre[i][j]<=pre[i][s.top()]) s.pop();
l[j]=s.size()==0?1:s.top()+1;
s.push(j);
}
while(!s.empty()) s.pop();
for(int j=m;j>=1;j--)
{
while(!s.empty()&&pre[i][j]<=pre[i][s.top()])
s.pop();
r[j]=s.size()==0?m:s.top()-1;
s.push(j);
}
while(!s.empty()) s.pop();
for(int j=1;j<=m;j++)
{
if(r[j]==fr&&l[j]==fl&&i==fi) continue;
int now=pre[i][j]*(r[j]-l[j]+1);
if(now>max2){
max2=now;
}
}
}
int temp=max1-min(ppp,yyy);
if(max2<temp) cout<<temp<<endl;
else cout<<max2<<endl;
return 0;
}