雅礼集训2017day4乱写
作者:互联网
day3找不到
先考虑洗涤过程,根据贪心的想法,我们只要每次选择结束时间最早的机器使用就好啦
而且这个过程中每件衣服洗好的时间的一定的,可以记录下来
再考虑烘干,如果我们二分答案,然后用类似的方法记录下来每个被烘干的衣服需要从什么时候开始烘干
那么令洗涤最晚的衣服用烘干最晚的机器,洗涤最早的用烘干最早的,一定是最优的方案
判断一下是否满足所有配对就好了
复杂度\(O(nlog^2n)\)
仔细一想好像根本不用二分,我们直接按照洗涤的方案处理烘干时间,再配对之后取最大值就可以了
#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define mid ((l+r)>>1)
#define y1 qwq
#define id(x,y) (((x)-1)*m+(y))
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
const int N=1e6+10,inf=1<<30;
int n,n1,n2,l,r,ret;
int a[N],b[N];
int c[N],d[N];
struct node
{
int x,y;
inline bool operator < (const node &t) const
{
return x>t.x;
}
};
priority_queue<node> q1,q2;
inline void main()
{
n=read(),n1=read(),n2=read();
for(int i=1;i<=n1;++i) a[i]=read(),q1.push((node){a[i],a[i]});
for(int i=1;i<=n2;++i) b[i]=read(),q2.push((node){b[i],b[i]});
for(int i=1;i<=n;++i)
{
node now=q1.top();q1.pop();
c[i]=now.x;
q1.push((node){now.x+now.y,now.y});
now=q2.top();q2.pop();
d[i]=now.x;
q2.push((node){now.x+now.y,now.y});
}
for(int i=1;i<=n;++i)
{
ret=max(ret,c[i]+d[n-i+1]);
}
printf("%lld\n",ret);
}
}
signed main()
{
red::main();
return 0;
}
题外话:写完口胡了一下\(3-n\)个机器的做法:把前两个机器花的时候合并成一个,然后数学归纳
看见这个数据范围应该对搜索有信心。。
考虑一下部分分:只要向右走就能安排上的情况
来一个我想不到的\(dp\)状态:\(f[i][j][S]\)表示当前已经完成的信息集合是\(S\),正在处理第\(i\)条信息,已经完成了\(j\)个数字
我们发现有些信息之间存在一定的包含关系
例如两个信息:\(\{1,4,5,6\}\)和\(\{5,1,4,6\}\)
如果我们完成了第一个信息的\(\{1,4\}\),然后继续完成了第二条信息,那么第一条信息也满足了
所以我们可以直接从第一条信息的第\(2\)个数字跳转到第二条信息的第\(0\)个数字
也就是
\(f[1][2][s]->f[2][0][s|(1<<1)]\)
这是一种转移方式,另一种是按部就班地完成当前信息
然后知道这个以后可以记忆化搜索得到答案
#include<bits/stdc++.h>
using namespace std;
namespace red{
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define mid ((l+r)>>1)
#define y1 qwq
#define id(x,y) (((x)-1)*m+(y))
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
const int N=1e6+10,inf=0x3f3f3f3f;
int n,S,ans;
int a[12][12],s[12],b[12],bit[12];
bool e[12][12],c[12][12][12];
bool in[12];
int f[12][12][2010];
bool g[12][12][2010];
inline bool check(int id,int len,int to)
{
int pos=0;
memset(in,0,sizeof(in));
for(int i=1;i<=len;++i)
in[a[id][i]]=1;
for(int i=1;i<=s[to];++i)
{
if(in[a[to][i]]) continue;
b[++pos]=a[to][i];
in[a[to][i]]=1;
}
if(pos!=s[id]-len) return 0;
for(int i=len+1;i<=s[id];++i)
if(a[id][i]!=b[i-len]) return 0;
return 1;
}
inline void dfs(int id,int pos,int st)
{
if(g[id][pos][st])
{
ans=min(ans,f[id][pos][st]);
return;
}
for(int i=1;i<=n;++i)
{
if(i!=id&&(bit[i]&st)==0)
if(c[id][pos][i]&&f[i][0][st|bit[id]]>f[id][pos][st])
{
f[i][0][st|bit[id]]=f[id][pos][st];
dfs(i,0,st|bit[id]);
}
}
if(pos!=s[id]&&f[id][pos+1][st]>f[id][pos][st]+1)
{
f[id][pos+1][st]=f[id][pos][st]+1;
dfs(id,pos+1,st);
}
}
inline void main()
{
n=read();S=(1<<n)-1;
for(int x,i=1;i<=n;++i)
{
bit[i]=1<<(i-1);
while(x=read())
{
a[i][++s[i]]=x;
e[i][x]=1;
}
}
for(int i=1;i<=n;++i)
{
for(int j=0;j<=s[i];++j)
{
for(int k=1;k<=n;++k)
{
c[i][j][k]=check(i,j,k);
}
}
}
memset(f,0x3f,sizeof(f));
ans=inf;
for(int i=1;i<=n;++i) g[i][s[i]][S^bit[i]]=1;
for(int i=1;i<=n;++i)
{
f[i][0][0]=0;
dfs(i,0,0);
}
printf("%d\n",ans==inf?-1:ans);
}
}
signed main()
{
red::main();
return 0;
}
满分算法很相似,只要再加两维表示正在倒序处理第\(k\)条信息,已经处理完成了第\(p\)位
#include<bits/stdc++.h>
using namespace std;
namespace red{
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define mid ((l+r)>>1)
#define y1 qwq
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
const int N=1e6+10,inf=0x3f3f3f3f;
int n,S,ans;
int a[12][12],s[12],bit[12];
int f[12][12][12][12][1050];
bool e[12][12][12],c[12][12][12];
bool in[12];
bool g[12][12][12][12][1050];
set<long long> ext;
inline bool check(int id,int len,int to)
{
int pos=0;
memcpy(in,e[id][len],sizeof(in));
for(int i=1;i<=s[to];++i)
{
if(in[a[to][i]]) continue;
++pos,in[a[to][i]]=1;
if(a[to][i]!=a[id][len+pos]) return 0;
}
if(pos!=s[id]-len) return 0;
return 1;
}
#define cover(id1,pos1,id2,pos2,st,add) (k=min(dfs(id1,pos1,id2,pos2,st)+add,k))
inline int dfs(int id1,int pos1,int id2,int pos2,int st)
{
if(st==S&&pos1==s[id1]&&!pos2) return 0;
int &k=f[id1][pos1][id2][pos2][st];
if(g[id1][pos1][id2][pos2][st]) return k;
g[id1][pos1][id2][pos2][st]=1;
if(id2&&!pos2)
{
for(int i=0;i<=n;++i)
if(i!=id1&&!(bit[i]&st))
for(int j=0;j<=s[i];++j)
if(c[i][j][id2])
cover(id1,pos1,i,j,st|bit[i],0);
}
for(int i=1;i<=n;++i)
if(c[id1][pos1][i]&&!(bit[i]&st))
cover(i,0,id2,pos2,st|bit[i],0);
if(pos1==s[id1]&&!pos2) return k;
if(pos1!=s[id1]&&(e[id2][pos2+1][a[id1][pos1+1]]||!id2))
cover(id1,pos1+1,id2,pos2,st,1);
if(pos2&&(e[id1][pos1][a[id2][pos2]]||!id1))
cover(id1,pos1,id2,pos2-1,st,1);
if(pos1!=s[id1]&&pos2&&a[id2][pos2]==a[id1][pos1+1])
cover(id1,pos1+1,id2,pos2-1,st,1);
return k;
}
inline void main()
{
n=read();
long long key;
for(int x,i=1;i<=n;++i)
{
s[i]=0,key=0;
bit[i]=1<<(i-1);
memset(e[i],0,sizeof(e[i]));x=1;
while(x)
{
x=read();
key=(key<<1)+(key<<3)+x;
a[i][++s[i]]=x;
for(int k=1;k<=s[i];++k)
if(a[i][k]) e[i][s[i]][a[i][k]]=1;
}
--s[i];
if(ext.count(key)) --i,--n;
ext.insert(key);
}
S=(1<<n)-1;
for(int i=1;i<=n;++i)
{
c[0][0][i]=1;
for(int j=0;j<=s[i];++j)
{
for(int k=1;k<=n;++k)
{
c[i][j][k]=check(i,j,k);
}
}
}
memset(f,0x3f,sizeof(f));
ans=inf;
for(int i=1;i<=n;++i)
ans=min(ans,dfs(0,0,i,s[i],bit[i]));
printf("%d\n",ans==inf?-1:ans);
}
}
signed main()
{
red::main();
return 0;
}
标签:ch,2017day4,乱写,pos,雅礼,int,define,id,getchar 来源: https://www.cnblogs.com/knife-rose/p/12748654.html