JZOJ 1284 病毒
题目大意
选择一些二进制数,使它们的或值二进制1的个数不超过 k k k并使选择的个数最大
分析
可以反其道而行,用 s u m [ t ] sum[t] sum[t]表示二进制为 t t t时,选择某头牛的二进制与 t t t没有交集的个数,那么答案就是这个东西对吧
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
typedef unsigned short ust;
ust sum[32768],q[32768],lg[32768],n,m,k,cnt,ans;
inline ust iut(){
rr ust ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
signed main(){
n=iut(); m=iut(); k=m-iut();
if (!k) q[++cnt]=0; else
for (rr ust i=1;i<(1<<m);++i){
lg[i]=lg[i&(i-1)]+1;
if (lg[i]==k) q[++cnt]=i;
}
for (rr ust i=1;i<=n;++i){
rr ust t=0;
for (rr ust p=iut();p;--p)
t|=1<<(iut()-1);
for (rr ust j=1;j<=cnt;++j)
if (!(q[j]&t)) ++sum[j];
}
for (rr ust i=1;i<=cnt;++i) ans=ans>sum[i]?ans:sum[i];
return !printf("%d\n",ans);
}
JZOJ 1285 奶酪厂(题目过水)
JZOJ 1286 太空电梯
题目
奶牛们想用 K ( 1 < = K < = 400 ) K(1<=K<=400) K(1<=K<=400)中石块制造一个太空电梯去太空旅行,每种石块有自己的高度 h i ( 1 < = h i < = 100 ) h_i(1<=h_i<=100) hi(1<=hi<=100)和数量 c i ( 1 < = c i < = 10 ) c_i(1<=c_i<=10) ci(1<=ci<=10),为了避免宇宙射线的干扰,每种石块不能超过最高可以达到的高度 a i ( 1 < = a i < = 40000 ) a_i(1<=a_i<=40000) ai(1<=ai<=40000)。帮助奶牛用石块堆积一个最高的太空电梯。
分析
那么这道题主要受到了最高高度的限制,那么可以用贪心的方法,先把 a i a_i ai从小到大排序,这样可以让高度限制小的先进行,那么剩下就是一个多重背包了
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
struct rec{int w,lim,s;}a[401];
bool f[40001]; int n;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
bool cmp(rec a,rec b){
return a.lim<b.lim||(a.lim==b.lim&&a.s*a.w>b.s*b.w);
}
signed main(){
n=iut(); f[0]=1;
for (rr int i=1;i<=n;++i) a[i]=(rec){iut(),iut(),iut()};
sort(a+1,a+1+n,cmp);
for (rr int i=1;i<=n;++i)
for (rr int j=1;j<=a[i].s;++j)
for (rr int k=a[i].lim-a[i].w;k>=0;--k)
if (f[k]) f[k+a[i].w]=1;
while (!f[a[n].lim]) --a[n].lim;
return !printf("%d\n",a[n].lim);
}
JZOJ 1287 躲雨
题目
农场有 F ( 1 < = F < = 200 ) F(1<=F<=200) F(1<=F<=200)个奶牛吃草的区域,有 P ( 1 < = P < = 1500 ) P(1<=P<=1500) P(1<=P<=1500)条路连接一些区域,路是双向的。有些区域有遮雨棚,每个遮雨棚有自己的容量限制。现在要你计算所有牛都能找到地方躲雨最少需要多少时间。
分析
那么可以二分答案,然后跑网络流判定是否所有牛都能到达雨棚,但是改题的时候改了十几次,主要是因为取值不够的问题,以及二分的答案不合法
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#include <queue>
#define rr register
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
struct node{int y,w,next;}e[81001]; ll dist[201][201];
int n,m,hav[201],lim[201],s,t,k,ls[411],dis[411],sum;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void add(int x,int y,int w){
e[++k]=(node){y,w,ls[x]}; ls[x]=k;
e[++k]=(node){x,0,ls[y]}; ls[y]=k;
}
inline signed bfs(int s){
for (rr int i=1;i<=t;++i) dis[i]=0;
rr queue<int>q; q.push(s); dis[s]=1;
while (q.size()){
rr int x=q.front(); q.pop();
for (rr int i=ls[x];i;i=e[i].next)
if (e[i].w>0&&!dis[e[i].y]){
dis[e[i].y]=dis[x]+1;
if (e[i].y==t) return 1;
q.push(e[i].y);
}
}
return 0;
}
inline signed dfs(int x,int now){
if (x==t||!now) return now;
rr int rest=0,f;
for (rr int i=ls[x];i;i=e[i].next)
if (e[i].w>0&&dis[e[i].y]==dis[x]+1){
rest+=(f=dfs(e[i].y,min(now-rest,e[i].w)));
e[i].w-=f; e[i^1].w+=f;
if (now==rest) return rest;
}
if (!rest) dis[x]=0;
return rest;
}
inline bool check(ll mid){
memset(ls,0,sizeof(ls)); k=1;
for (rr int i=1;i<=n;++i){
add(s,i,hav[i]),add(i+n,t,lim[i]);
for (rr int j=1;j<=n;++j)
if (dist[i][j]<=mid) add(i,j+n,1e9);
}
rr int ans=0;
while (bfs(s)) ans+=dfs(s,1e9);
return ans==sum;
}
signed main(){
n=iut(),m=iut(); s=n<<1|1,t=s+1;
memset(dist,63,sizeof(dist));
for (rr int i=1;i<=n;++i) sum+=(hav[i]=iut()),lim[i]=iut(),dist[i][i]=0;
while (m--){
rr int x=iut(),y=iut(),w=iut();
dist[x][y]=dist[y][x]=min(dist[x][y],w);
}
for (rr int k=1;k<=n;++k)
for (rr int i=1;i<=n;++i)
for (rr int j=1;j<=n;++j)
dist[i][j]=min(dist[i][k]+dist[k][j],dist[i][j]);
rr ll l=0,r=2e11;
while (l<r){
rr ll mid=(l+r)>>1;
if (check(mid)) r=mid;
else l=mid+1;
}
if (!check(l)) l=-1;
return !printf("%lld",l);
}