D:https://ac.nowcoder.com/acm/contest/882/D
给出n,k,n个数,求第k小团。用bitset。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef bitset<105> b;
ll a[105];
b bb[105];
struct node
{
ll v;
b w;
bool operator <(const node &a)const{
return a.v<v;
}
};
priority_queue<node> q;
int main()
{
ll n,k;
scanf("%lld%lld",&n,&k);
for(ll i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
char str[105];
for(ll i=1;i<=n;i++){
scanf("%s",str+1);
for(ll j=1;j<=n;j++){
if(str[j]=='1'){
bb[i].set(j);
}
}
}
node e;
e.v=0;
e.w.reset();//重置
q.push(e);
ll cnt=0;
while(cnt<k){
if(q.empty()){
printf("-1\n");
return 0;
}
if(cnt==k-1){
printf("%lld\n",q.top().v);
return 0;
}
node f=q.top();
ll val=f.v;
b bit=f.w;
q.pop();
ll pos=1;
for(ll i=1;i<=n;i++){
if(bit[i]){
pos=i+1;
}
}
//记录每次最后一位是1的位置
for(ll i=pos;i<=n;i++){
//是0并且能加进去
if(bit[i]==0&&((bit&bb[i])==bit)){
node ff;
b g=bit;
g.set(i);//把这位置1
ff.w=g;
ff.v=val+a[i];//加上这一位
q.push(ff);
}
}
cnt++;
}
return 0;
}
F:https://ac.nowcoder.com/acm/contest/882/F
给出2n个人,及每两人之间的竞争力。把这两人分成两组,同一组间竞争力为0,最大化一个人和另一队所有人的竞争力
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[30][30],s[30],n,mx=0,ans=0;
vector<ll> v;
void dfs(ll num)
{
//选够n个
if(v.size()==n){
mx=max(mx,ans);
return ;
}
//所选的超过2*n个
if(num==2*n+1){
return ;
}
//把num加进去该队的影响,和所有人的和
ll f=s[num];
//减去和它成为一队的
for(int i=0;i<v.size();i++){
f-=a[num][v[i]]*2;
}
ans+=f;
v.push_back(num);
dfs(num+1);
ans-=f;
v.pop_back();
dfs(num+1);
}
int main()
{
scanf("%lld",&n);
for(ll i=1;i<=2*n;i++){
for(ll j=1;j<=2*n;j++){
scanf("%lld",&a[i][j]);
s[i]+=a[i][j];
}
}
dfs(1);
printf("%lld\n",mx);
return 0;
}
H:https://ac.nowcoder.com/acm/contest/882/H
求第二大的矩阵,全是1.
这个有模板,悬线法,找到每个点最左端到哪儿,最右端到哪儿,还有上端到哪儿。
还有一种做法,取每个位置的高度,宽度初始为1,在高度存在的情况下,不断向左扩展,逐个更新计算。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
char s[maxn];
int dp[maxn][maxn],st[maxn],n,m;
int mx=0,mxx=0,top;
void add(int x,int y)
{
int area=x*y;
if(area>=mx){
mxx=mx;
mx=area;
}
else if(area>mxx){
mxx=area;
}
}
int main()
{
memset(dp,0,sizeof(dp));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%s",&s);
for(int j=1;j<=m;j++){
if(s[j-1]=='1') dp[i][j]=1;
dp[i][j]+=dp[i-1][j]*dp[i][j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int len=dp[i][j],dep=1;
while(len){
add(dep,len);
len=min(len,dp[i][j-dep]);
dep++;
}
}
}
printf("%d\n",mxx);
return 0;
}