题目
思路
暴力dfs会TLE,考虑折半搜索
将每次任务分为左边获得的和右边获得的
即
l
1
+
r
1
=
l
2
+
r
2
=
l
3
+
r
+
3
l_1+r_1=l_2+r_2=l_3+r+3
l1+r1=l2+r2=l3+r+3
为了让左边搜索时只依赖l,右边只依赖r,所以移项变为
r
1
−
r
2
=
l
2
−
l
1
r_1-r_2=l_2-l_1
r1−r2=l2−l1,
r
1
−
r
3
=
l
3
−
l
1
r_1-r_3=l_3-l_1
r1−r3=l3−l1
先搜左边,将所得的
l
2
−
l
1
l_2-l_1
l2−l1和
l
3
−
l
1
l_3-l_1
l3−l1存入pair中作为key在map中指向结构体tmp
tmp存得到这个pair的步骤(xu数组)和
l
1
l_1
l1
为了让
l
1
l_1
l1尽可能大,我们在更新时只存
l
1
l_1
l1较大的tmp
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=30;
int n;
int a[maxn],b[maxn],c[maxn];
int opt[maxn],now[maxn];
char ANS[][3]={"xx","LM","MW","LW"};
struct node{
int xu[maxn];
int l1;
node() { l1=0;memset(xu,0,sizeof(xu)); }
};
map<pair<int,int>,node> mp;
int ans=-1e9;
void cpy(int *a,int *b,int st,int en) { for(int i=st;i<=en;i++) a[i]=b[i]; }
void dfs1(int i,int l1,int l2,int l3){
if(i==n/2+1){
int a1=l2-l1,a2=l3-l1;
pair<int,int> t=make_pair(a1,a2);
if(mp.count(t)&&mp[t].l1>l1) return;
node tmp;tmp.l1=l1;
cpy(tmp.xu,now,1,n/2);//前半部分的步骤
mp[t]=tmp;
return;
}
//模拟三种情况
now[i]=1,dfs1(i+1,l1+a[i],l2+b[i],l3);
now[i]=2,dfs1(i+1,l1,l2+b[i],l3+c[i]);
now[i]=3,dfs1(i+1,l1+a[i],l2,l3+c[i]);
}
void dfs2(int i,int r1,int r2,int r3){
if(i==n+1){
int b1=r1-r2,b2=r1-r3;
pair<int,int> t=make_pair(b1,b2);
if(!mp.count(t)) return;
if(mp[t].l1+r1>ans) cpy(opt,mp[t].xu,1,n/2),cpy(opt,now,n/2+1,n),ans=mp[t].l1+r1;
return;
}
now[i]=1,dfs2(i+1,r1+a[i],r2+b[i],r3);
now[i]=2,dfs2(i+1,r1,r2+b[i],r3+c[i]);
now[i]=3,dfs2(i+1,r1+a[i],r2,r3+c[i]);
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i]>>b[i]>>c[i];
dfs1(1,0,0,0),dfs2(n/2+1,0,0,0);
if(ans==-1e9) { cout<<"Impossible";return 0; }
for(int i=1;i<=n;i++) cout<<ANS[opt[i]]<<endl;
return 0;
}
end
完结撒花