Avito Code Challenge 2018 D. Bookshelves(贪心+bfs)

题目链接:http://codeforces.com/contest/981/problem/D


假设答案为ans,则一定从1走k步到n,每条边&ans的值为ans,边的权重为区间的和,然后贪心从高位枚举,如果这一位可以为1,则把这一位赋值为1,最后即可得到答案


代码:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=55;
typedef long long ll;
struct Edge
{
	int v,nxt;
	ll w;
}E[MAXN*MAXN];
int head[MAXN],tot;
ll a[MAXN],ans;
void init()
{
	tot=0;a[0]=0;ans=0;
	memset(head,-1,sizeof(head));
}
void addedge(int u,int v,ll w)
{
	E[tot].v=v;E[tot].w=w;E[tot].nxt=head[u];
	head[u]=tot++;
}
int n,k;
struct node
{
	int now,st;
	node(int _now=0,int _st=0):now(_now),st(_st){}
};
bool vis[MAXN][MAXN];
bool bfs(ll now)
{
	queue<node> Q;
	Q.push(node(1,0));
	vis[1][0]=true;
	memset(vis,false,sizeof(vis));
	while(!Q.empty())
	{
		node T=Q.front();
		Q.pop();
		int id=T.now;
		int st=T.st;
		for(int i=head[id];~i;i=E[i].nxt)
		{
			int v=E[i].v;
			if((E[i].w&now)!=now) continue;
			if(!vis[v][st+1])
			{
				vis[v][st+1]=true;
				Q.push(node(v,st+1));
			}
		}
	}
	return vis[n+1][k];
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	init();
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
		a[i]+=a[i-1];
	}
	for(int i=1;i<=n;i++)
		for(int j=i+1;j<=n+1;j++)
			addedge(i,j,a[j-1]-a[i-1]);
	ll now=0;
	for(int i=60;i>=0;i--)
	{
		now=ans|(1LL<<i);
		if(bfs(now)) ans|=(1LL<<i);
	}
	printf("%lld\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/sinat_32872703/article/details/80480729