4/4 贪心选数+最长上升子序列+简单染色二分图+二进制搜索
Posted 钟钟终
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了4/4 贪心选数+最长上升子序列+简单染色二分图+二进制搜索相关的知识,希望对你有一定的参考价值。
P6268 [SHOI2002]舞会
先染色区分男女生。再套二分匹配的板子,求出最小路径覆盖。
#include <bits/stdc++.h>
using namespace std;
const int maxn=1005;
int n,m,g[maxn][maxn],link[maxn],col[maxn];
bool used[maxn];
void cc(int u,int pre,int color)
col[u]=color;
for(int i=1;i<=n;i++)
if(g[u][i]&&!col[i])
cc(i,u,3-color);
return;
int dfs(int u)
for(int i=1;i<=n;i++)
if(col[i]==1) continue;
if(!used[i]&&g[u][i])
used[i]=1;
if(link[i]==-1||dfs(link[i]))
link[i]=u;return 1;
return 0;
int hungary()
int res=0;
memset(link,-1,sizeof(link));
for(int i=1;i<=n;i++)
if(col[i]==2) continue;
memset(used,0,sizeof(used));
if(dfs(i))
res++;
return res;
int main()
cin>>n>>m;
for(int i=1;i<=m;i++)
int u,v;cin>>u>>v;
u++;v++;
g[u][v]=g[v][u]=1;
for(int i=1;i<=n;i++) //区分男女生
if(!col[i]) cc(i,0,1);
cout<<n-hungary()<<endl;
return 0;
# C. Magical Rearrangement
一个较难的贪心细节题。
分为两大类:
如果0的数目不是最多时,无解的情况:1.mx>=rest+2
如果0的数目是最多的,无解的情况:2.mx>=rest+1
一组特判:rest==0,num[0]==1,此时输出一个0
put(int last)函数的作用:当前选的数字不能和last相同,满足相邻两位不同;
由于不能拥有前导0,因此从0开始。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int num[15];
int put(int last)
for(int i=0;i<=9;i++)
if(num[i]==0||i==last)
continue;
num[i]--;
int id=0,rest=0,mx=0;
for(int j=0;j<=9;j++)
rest+=num[j];
if(mx<num[j])
mx=num[j];id=j;
rest-=mx;
if((id==i&&mx>=rest+1)||(id!=i&&mx>=rest+2))
num[i]++;
else
return i;
return -1;
signed main()
int t;cin>>t;
while(t--)
int rest=0,mx=0,id;
for(int i=0;i<=9;i++)
cin>>num[i];
rest+=num[i];
if(mx<num[i])
mx=num[i],id=i;
rest-=mx;
if(rest==0&&num[0]==1)
cout<<0<<endl;continue;
if(id==0&&mx>=rest+1)
cout<<-1<<endl;continue;
else if(id!=0&&mx>=rest+2)
cout<<-1<<endl;continue;
int x=put(0);
while(x>=0)
cout<<x;x=put(x);
cout<<endl;
return 0;
# P1091 [NOIP2004 提高组] 合唱队形
求出两个最长上升子序列,拼接长度减去重复记的自身(减去1即可)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int a[105],f[105],d[105];
signed main()
int n;cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i],f[i]=d[i]=1;
for(int i=2;i<=n;i++)
for(int j=1;j<i;j++)
if(a[i]>a[j])
f[i]=max(f[i],f[j]+1);
for(int i=n-1;i>=1;i--)
for(int j=i+1;j<=n;j++)
if(a[i]>a[j])
d[i]=max(d[i],d[j]+1);
int ans=0;
for(int i=1;i<=n;i++)
ans=max(ans,f[i]+d[i]-1);
cout<<n-ans<<endl;
return 0;
P1461 [USACO2.1]海明码 Hamming Codes
一道二进制的搜索题。
1.两个数字异或能统计出有多少个1.
2.要保证序列最小,第一个数字肯定是0.
#include <bits/stdc++.h>
using namespace std;
const int maxn=1005;
int n,b,d,a[105],cnt;
int check(int x,int y)
int g=x^y;
int num=0;
while(g)
if(g%2==1) num++;
g/=2;
return num;
int main()
cin>>n>>b>>d;
a[++cnt]=0;
int mx=1<<b;
while(cnt<n)
for(int i=a[cnt]+1;i<mx;i++)
if(check(a[cnt],i)>=d)
int f=0;
for(int j=1;j<=cnt-1;j++)
if(check(a[j],i)<d)
f=1;break;
if(!f)
a[++cnt]=i;
for(int i=1;i<=n;i++)
cout<<a[i]<<" ";
if(i%10==0) cout<<endl;
return 0;
以上是关于4/4 贪心选数+最长上升子序列+简单染色二分图+二进制搜索的主要内容,如果未能解决你的问题,请参考以下文章
贪心+二分查找:最长上升子序列(3.14 leetcode每日打卡)