分析

测试点1、2:搜索+剪枝。

测试点3:只有一个抽屉,直接01背包。

测试点4、5:每个物品体积相同,说明每个抽屉能放下的物品个数固定,建图跑费用流。

测试点6:每个物品体积相近,经过验证发现每个抽屉能放下的物品个数仍然固定,费用流。

测试点7:除了第一个物品,其他物品体积相同。所以可以枚举第一个物品放在哪个抽屉,然后费用流。

测试点8、9、10:随机化贪心,如果不是人品爆发基本不可能过(博主没过)。

代码

测试点3

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#define rin(i,a,b) for(int i=(a);i<=(b);i++)
#define rec(i,a,b) for(int i=(a);i>=(b);i--)
#define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
typedef long long LL;
using std::cin;
using std::cout;
using std::endl; inline int read(){
int x;scanf("%d",&x);return x;
} const int MAXN=2005;
const int MAXS=10005;
int n,m,s,v[MAXN],w[MAXN];
int f[MAXN][MAXS],pre[MAXN][MAXS];
int ans[MAXN]; int main(){
freopen("drawer3.in","r",stdin);
freopen("drawer3.out","w",stdout);
n=read(),m=read();
rin(i,1,n) v[i]=read();
s=read();
rin(i,1,n) w[i]=read();
rin(i,1,n) rec(j,s,v[i]){
f[i][j]=f[i-1][j];
pre[i][j]=j;
if(f[i-1][j-v[i]]+w[i]>f[i][j]){
f[i][j]=f[i-1][j-v[i]]+w[i];
pre[i][j]=j-v[i];
}
}
int now=s,pos=n;
while(pos){
if(pre[pos][now]<now) ans[pos]=1;
now=pre[pos][now];
pos--;
}
rin(i,1,n) printf("%d ",ans[i]);
printf("\n");
return 0;
}

测试点4、5、6

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <queue>
#define rin(i,a,b) for(int i=(a);i<=(b);i++)
#define rec(i,a,b) for(int i=(a);i>=(b);i--)
#define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
typedef long long LL;
using std::cin;
using std::cout;
using std::endl; inline int read(){
int x;scanf("%d",&x);return x;
} const int MAXN=1005;
const int MAXM=205;
int n,m,S,T,mincost,v,c[MAXM],w[MAXN][MAXM],ecnt=1,head[MAXN+MAXM];
int dis[MAXN+MAXM],pre[MAXN+MAXM];
bool book[MAXN+MAXM];
std::queue<int> q;
struct Edge{
int to,nxt,cap,ost;
}e[(MAXN+MAXM+MAXN*MAXM)<<1]; inline void add_edge(int bg,int ed,int cap,int ost){
ecnt++;
e[ecnt].to=ed;
e[ecnt].nxt=head[bg];
e[ecnt].cap=cap;
e[ecnt].ost=ost;
head[bg]=ecnt;
} inline bool spfa(){
memset(dis,0x3f,sizeof dis);
while(!q.empty()) q.pop();
dis[S]=0;
q.push(S);
book[S]=1;
while(!q.empty()){
int x=q.front();q.pop();
trav(i,x){
int ver=e[i].to;
if(dis[ver]>dis[x]+e[i].ost&&e[i].cap){
dis[ver]=dis[x]+e[i].ost;
pre[ver]=i;
if(!book[ver]){
q.push(ver);
book[ver]=1;
}
}
}
book[x]=0;
}
return dis[T]<1e9;
} inline void upd(){
int now=T,flow=1e9;
while(now!=S){
flow=std::min(flow,e[pre[now]].cap);
now=e[pre[now]^1].to;
}
now=T;
while(now!=S){
e[pre[now]].cap-=flow;
e[pre[now]^1].cap+=flow;
now=e[pre[now]^1].to;
}
mincost+=flow*dis[T];
} inline void ek(){
while(spfa()) upd();
} int main(){
freopen("drawer6.in","r",stdin);
freopen("drawer6.out","w",stdout);
n=read(),m=read();
S=n+m+1,T=S+1;
rin(i,1,n){
v=read();
add_edge(S,i,1,0);
add_edge(i,S,0,0);
}
rin(i,1,m){
c[i]=read()/v;
add_edge(n+i,T,c[i],0);
add_edge(T,n+i,0,0);
}
rin(i,1,n) rin(j,1,m){
w[i][j]=read();
add_edge(i,n+j,1,-w[i][j]);
add_edge(n+j,i,0,w[i][j]);
}
ek();
rin(i,1,n){
bool flag=0;
trav(j,i){
int ver=e[j].to;
if(ver==S) continue;
if(!e[j].cap){
printf("%d ",ver-n);
flag=1;break;
}
}
if(!flag) printf("0 ");
}
printf("\n");
return 0;
}

测试点7

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <queue>
#define rin(i,a,b) for(int i=(a);i<=(b);i++)
#define rec(i,a,b) for(int i=(a);i>=(b);i--)
#define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
typedef long long LL;
using std::cin;
using std::cout;
using std::endl; inline int read(){
int x;scanf("%d",&x);return x;
} const int MAXN=1005;
const int MAXM=205;
int n,m,S,T,mincost,v,c[MAXM],w[MAXN][MAXM],ecnt=1,head[MAXN+MAXM];
int dis[MAXN+MAXM],pre[MAXN+MAXM];
bool book[MAXN+MAXM];
std::queue<int> q;
struct Edge{
int to,nxt,cap,ost;
}e[(MAXN+MAXM+MAXN*MAXM)<<1]; inline void add_edge(int bg,int ed,int cap,int ost){
ecnt++;
e[ecnt].to=ed;
e[ecnt].nxt=head[bg];
e[ecnt].cap=cap;
e[ecnt].ost=ost;
head[bg]=ecnt;
} inline bool spfa(){
memset(dis,0x3f,sizeof dis);
while(!q.empty()) q.pop();
dis[S]=0;
q.push(S);
book[S]=1;
while(!q.empty()){
int x=q.front();q.pop();
trav(i,x){
int ver=e[i].to;
if(dis[ver]>dis[x]+e[i].ost&&e[i].cap){
dis[ver]=dis[x]+e[i].ost;
pre[ver]=i;
if(!book[ver]){
q.push(ver);
book[ver]=1;
}
}
}
book[x]=0;
}
return dis[T]<1e9;
} inline void upd(){
int now=T,flow=1e9;
while(now!=S){
flow=std::min(flow,e[pre[now]].cap);
now=e[pre[now]^1].to;
}
now=T;
while(now!=S){
e[pre[now]].cap-=flow;
e[pre[now]^1].cap+=flow;
now=e[pre[now]^1].to;
}
mincost+=flow*dis[T];
} inline void ek(){
while(spfa()) upd();
} int main(){
freopen("drawer7.in","r",stdin);
freopen("drawer7.out","w",stdout);
n=read(),m=read();
S=n+m+1,T=S+1;
int v1=read();
rin(i,2,n){
v=read();
}
rin(i,1,m){
c[i]=read();
}
rin(i,1,n) rin(j,1,m){
w[i][j]=read();
}
int minpos=-1,umincost=0;
rin(k,1,m){
ecnt=1,mincost=0;
memset(head,0,sizeof head);
c[k]-=v1;
mincost-=w[1][k];
rin(i,2,n){
add_edge(S,i,1,0);
add_edge(i,S,0,0);
}
rin(i,1,m){
add_edge(n+i,T,c[i]/v,0);
add_edge(T,n+i,0,0);
}
rin(i,2,n) rin(j,1,m){
add_edge(i,n+j,1,-w[i][j]);
add_edge(n+j,i,0,w[i][j]);
}
ek();
if(mincost<umincost){
umincost=mincost;
minpos=k;
}
c[k]+=v1;
}
ecnt=1,mincost=0;
memset(head,0,sizeof head);
rin(i,2,n){
add_edge(S,i,1,0);
add_edge(i,S,0,0);
}
rin(i,1,m){
add_edge(n+i,T,c[i]/v,0);
add_edge(T,n+i,0,0);
}
rin(i,2,n) rin(j,1,m){
add_edge(i,n+j,1,-w[i][j]);
add_edge(n+j,i,0,w[i][j]);
}
ek();
if(mincost<umincost){
umincost=mincost;
minpos=0;
}
else{
int k=minpos;
ecnt=1,mincost=0;
memset(head,0,sizeof head);
c[k]-=v1;
mincost-=w[1][k];
rin(i,2,n){
add_edge(S,i,1,0);
add_edge(i,S,0,0);
}
rin(i,1,m){
add_edge(n+i,T,c[i]/v,0);
add_edge(T,n+i,0,0);
}
rin(i,2,n) rin(j,1,m){
add_edge(i,n+j,1,-w[i][j]);
add_edge(n+j,i,0,w[i][j]);
}
ek();
}
printf("%d ",minpos);
rin(i,2,n){
bool flag=0;
trav(j,i){
int ver=e[j].to;
if(ver==S) continue;
if(!e[j].cap){
printf("%d ",ver-n);
flag=1;break;
}
}
if(!flag) printf("0 ");
}
printf("\n");
return 0;
}

测试点8、9、10

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <ctime>
#include <vector>
#define rin(i,a,b) for(int i=(a);i<=(b);i++)
#define rec(i,a,b) for(int i=(a);i>=(b);i--)
#define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
typedef long long LL;
using std::cin;
using std::cout;
using std::endl; inline int read(){
int x;scanf("%d",&x);return x;
} const int MAXN=1005;
const int MAXM=305;
int n,m,v[MAXN],c[MAXM],blg[MAXN];
bool vis[MAXN];
std::vector<int> vec[MAXM],maxvec[MAXM];
struct Pair{
int id,w;
inline friend bool operator < (Pair A,Pair B){
return 1.0*A.w/v[A.id]>1.0*B.w/v[B.id];
}
}a[MAXM][MAXN]; inline int work(){
memset(vis,0,sizeof vis);
int ret=0;
rin(i,1,m){
vec[i].clear();
int rem=c[i];
rin(j,1,n){
if(vis[a[i][j].id]||rem<v[a[i][j].id]) continue;
if((rand()%(n*2))>n+vec[i].size()) continue;
vec[i].push_back(a[i][j].id);
vis[a[i][j].id]=1;
rem-=v[a[i][j].id];
ret+=a[i][j].w;
}
}
return ret;
} int main(){
freopen("drawer10.in","r",stdin);
freopen("drawer10.out","w",stdout);
srand(time(0));
n=read(),m=read();
rin(i,1,n) v[i]=read();
rin(i,1,m) c[i]=read();
rin(i,1,n) rin(j,1,m) a[j][i]=(Pair){i,read()};
rin(i,1,m) std::sort(a[i]+1,a[i]+n+1);
int maxans=0;
rin(k,1,10000){
int temp=work();
if(temp>maxans){
memset(blg,0,sizeof blg);
rin(i,1,m) rin(j,0,(int)vec[i].size()-1)
blg[vec[i][j]]=i;
maxans=temp;
}
}
rin(i,1,n) printf("%d ",blg[i]);
printf("\n");
return 0;
}

[LOJ2288][THUWC2017]大葱的神力:搜索+背包DP+费用流+随机化的更多相关文章

  1. 配置魔药 [NOIP模拟] [DP] [费用流]

    问题描述在<Harry Potter and the Chamber of Secrets>中,Ron 的魔杖因为坐他老爸的 Flying Car 撞到了打人柳,不幸被打断了,从此之后,他 ...

  2. AIM Tech Round 3 (Div. 1) (构造,树形dp,费用流,概率dp)

    B. Recover the String 大意: 求构造01字符串使得子序列00,01,10,11的个数恰好为$a_{00},a_{01},a_{10},a_{11}$ 挺简单的构造, 注意到可以通 ...

  3. 背包dp整理

    01背包 动态规划是一种高效的算法.在数学和计算机科学中,是一种将复杂问题的分成多个简单的小问题思想 ---- 分而治之.因此我们使用动态规划的时候,原问题必须是重叠的子问题.运用动态规划设计的算法比 ...

  4. LOJ 2288「THUWC 2017」大葱的神力

    LOJ 2288「THUWC 2017」大葱的神力 Link Solution 比较水的提交答案题了吧 第一个点爆搜 第二个点爆搜+剪枝,我的剪枝就是先算出 \(mx[i]\) 表示选取第 \(i \ ...

  5. Codeforces 946 课程表背包DP 数位DFS构造

    A B 给你A,B 两个数      1.a=0 OR b=0 break      2.a>=2b a=a-2b        3.b>=2a b=b-2a 如果只是单纯模拟肯定会超时 ...

  6. @loj - 2288@「THUWC 2017」大葱的神力

    目录 @description@ @solution@ @data - 1@ @data - 2@ @data - 3@ @data - 4@ @data - 5@ @data - 6@ @data ...

  7. hdu 5534 Partial Tree 背包DP

    Partial Tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid= ...

  8. HDU 5501 The Highest Mark 背包dp

    The Highest Mark Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?p ...

  9. Codeforces Codeforces Round #319 (Div. 2) B. Modulo Sum 背包dp

    B. Modulo Sum Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/577/problem/ ...

随机推荐

  1. 【QT开发】QT在windows下的exe应用程序如何在别人的电脑上直接运行

     当你利用QT编译了一个可执行程序,需要将这个可执行程序拷贝到别人的电脑上运行,这个时候除了这个可执行程序外,还需要支持的库才可用运行.一般来说通过下面的方法可以实现.     首先,需要看你用的是什 ...

  2. Windows.命令行(CMD)_执行命令&环境变量

    1.CMD命令中如果 命令有换行的话,就使用 ^来连接(这就类似于 Linux命令行中 \ 的作用) 2.环境变量 2.1.显示 所有环境变量的值,命令:set 2.2.显示 某个环境变量的值,命令 ...

  3. ES5中的继承

    继承 在面向对象的语言中, 大多语言都支持两种继承方式: 接口继承 和 实现继承, 接口继承 只继承方法签名, 实现继承 才继承实际的方法, ECMAScript 值支持 实现继承, 今天我们来谈谈实 ...

  4. 怎样用adb抓取log?

    在Android客户端的测试过程中,有时候我们会遇到闪退等异常情况.这时我们可以通过adb抓取log,从而给开发提供更多信息. 一.下载ADB.exe     在网上搜索“adb工具包”就可以找到很多 ...

  5. vue组件化编程应用

    写几个小案例来理解vue的组件化编程思想,下面是一个demo. 效果图示: 功能: Add组件用于添加用户评论,提交后右边评论回复会立马显示数据.Item组件点击删除可以删除当前用户评论.当List组 ...

  6. int快读

    昨天偶然间看到CJ_tony的快读,所以便决定学习一下. 这个快读的原理就是:读入单个字符要比读入读入数字快,先读入字符,然后再转化成数字.(原理的话大学再研究) 代码: #include<io ...

  7. ThinkPHP5微信支付扩展库(超级简单, 超级超好用!)

    ThinkPHP5微信支付最新扩展库(2017年9月24日). 我的想法很简单,就是只需要调用一个静态方法就可以完成支付,查询,退款,查账等等, 无需重复造轮子, 专注自己业务!欢迎到Github查看 ...

  8. JS的for循环包裹异步函数的问题

    有个循环,循环一个异步回调,为啥回调引用的循环值都是最后一步循环的循环值?然后,又有些时候无论什么循环值都得不到? var arr = [1,3,5,7,9]; var arrLength = arr ...

  9. Spring基础09——Bean的自动装配

    1.XML配置的Bean自动装配 SpringIOC容器可以自动装配Bean,需要做的仅仅是在<bean>的autowire属性里指定自动装配的模式,而不需要手工去指定要装配的Bean,a ...

  10. verilog中的timescale

    `timescale是Verilog HDL 中的一种时间尺度预编译指令,它用来定义模块的仿真 时的时间单位和时间精度.格式如下: `timescale  仿真时间单位/时间精度 注意:,不能为其它的 ...