题意就是
有3个人 最多25场比赛
给出每个人参加每场比赛的分数
每次比赛 你都可以选择两个人 加上那两个人的分数
最后求一个比赛完所有人分数相同的方案
如果有多个方案,求分数最大的方案
一开始看n=25
3^25太大了 根本做不完 于是就没多想 去搞别的题了
比赛完后看题目类型 meet-in-the-middle
据说白书上还有类似的题(自我反省啊!)
瞬间明白了
前一半暴力选择方案 扔map里
后一般暴力 map里查询
如果当前方案三个人的值分别是x,y,z
map可以只扔y-x,z-x的值 map的value保存a的值
如果有相同的key value取最大的
这样后一半暴力的三个人的值a,b,c
这样只需要查询 a-b,c-b的值 如果存在 那么value+a即为答案
这个代码跑了好长时间。。1900+ms 差点超时
如果直接循环方案对应的三进制数 是不是会更快一点呢?有空试试
如果不扔map 直接存的话 时间不到1s
#include<bits/stdc++.h>
using namespace std;
const int base=3;
struct node
{
long long y,z;
node(long long a,long long b)
{
y=a;
z=b;
}
bool operator< (const node &head) const
{
return head.y==y?head.z<z:head.y<y;
}
};
map<node,int>mp;
struct info
{
int choice;
long long x;
}f[2000001];
int m,n;
int has=0;
struct self
{
int x,y,z;
}s[33];
long long ans;
int choicex,choicey;
void predfs(int dep,long long x,long long y,long long z,int choice)
{
//for(int kk=1;kk<dep;kk++)
//cout<<" ";
//cout<<"dep="<<dep<<" x="<<x<<" y="<<y<<" z="<<z<<" choice="<<choice<<endl;
if(dep==n+1)
{
//cout<<" predfs dep="<<dep-1<<" "<<x<<" "<<y<<" "<<z<<endl;
y-=x;
z-=x;
node t=node(y,z);
if(mp.find(t)!=mp.end())
{
int pos=mp[t];
if(f[pos].x<x)
{
f[pos].x=x;
f[pos].choice=choice;
}
}
else
{
has++;
mp[t]=has;
f[has].x=x;
f[has].choice=choice;
//cout<<" add "<<y<<" "<<z<<" base="<<x<<" choice="<<choice<<endl;
}
return;
}
//1 2 1 3 2 3
for(int k=0;k<=2;k++)
{
if(k==0)
{
predfs(dep+1,x+s[dep].x,y+s[dep].y,z,choice*3+k);
}
if(k==1)
{
predfs(dep+1,x+s[dep].x,y,z+s[dep].z,choice*3+k);
}
if(k==2)
{
predfs(dep+1,x,y+s[dep].y,z+s[dep].z,choice*3+k);
}
}
}
void lowdfs(int dep,long long x,long long y,long long z,int choice)
{
if(dep==n)
{
y-=x;
z-=x;
node t=node(-y,-z);
if(mp.find(t)!=mp.end())
{
int pos=mp[t];
//cout<<" pre="<<f[pos].x<<" low="<<x<<endl;
{
if(f[pos].x+x>ans)
{
ans=f[pos].x+x;
//cout<<" ans="<<ans<<endl;
choicex=f[pos].choice;
choicey=choice;
}
}
}
return;
}
for(int k=0;k<=2;k++)
{
if(k==0)
{
lowdfs(dep-1,x+s[dep].x,y+s[dep].y,z,choice*3+k);
}
if(k==1)
{
lowdfs(dep-1,x+s[dep].x,y,z+s[dep].z,choice*3+k);
}
if(k==2)
{
lowdfs(dep-1,x,y+s[dep].y,z+s[dep].z,choice*3+k);
}
}
}
void rep(int i,int u)
{
if(i==1)
{
int t=u%3;
if(t==0)
printf("LM\n");
if(t==1)
printf("LW\n");
if(t==2)
printf("MW\n");
return;
}
rep(i-1,u/3);
int t=u%3;
if(t==0)
printf("LM\n");
if(t==1)
printf("LW\n");
if(t==2)
printf("MW\n");
}
void p(int i,int u)
{
while(i<=m)
{
int t=u%3;
u/=3;
i++;
if(t==0)
printf("LM\n");
if(t==1)
printf("LW\n");
if(t==2)
printf("MW\n");
}
}
void print(int l,int r)
{
//cout<<ans<<endl;
rep(n,l);
p(n+1,r);
}
int main()
{
ans=-1e14;
scanf("%d",&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&s[i].x,&s[i].y,&s[i].z);
if(m%2==0)
n=m/2;
else
n=m/2+1;
//cout<<"n="<<n<<endl;
predfs(1,0,0,0,0);
lowdfs(m,0,0,0,0);
//cout<<ans<<endl;
if(ans!=-1e14)
print(choicex,choicey);
else
printf("Impossible\n");
return 0;
}
直接存+排序+二分
980ms
#include<bits/stdc++.h>
using namespace std;
struct node
{
long long y,z;
long long x;
int choice;
};
node g[2000001];
int cmp(node head,node a)
{
if(head.y!=a.y)
return head.y<a.y;
if(head.z!=a.z)
return head.z<a.z;
return head.x>a.x;
}
struct info
{
int choice;
long long x;
}f[2000001];
int m,n;
int has=0;
struct self
{
int x,y,z;
}s[33];
long long ans;
int choicex,choicey;
int ipow(int i,int k)
{
if(k==0)
return 1;
return i*ipow(i,k-1);
}
void add(long long &a,long long &b,long long &c,int k,int i)
{
if(k==0)
{
a+=s[i].x;
b+=s[i].y;
}
if(k==1)
{
a+=s[i].x;
c+=s[i].z;
}
if(k==2)
{
b+=s[i].y;
c+=s[i].z;
}
}
void add(int u)
{
int v=u;
long long x=0,y=0,z=0;
for(int i=n;i>=1;i--)
{
add(x,y,z,v%3,i);
v/=3;
}
y-=x;
z-=x;
has++;
g[has].x=x;
g[has].y=y;
g[has].z=z;
g[has].choice=u;
}
int bs(long long y,long long z)
{
int l=1,r=has,mid,ret=0;
while(l<=r)
{
mid=(l+r)>>1;
if(g[mid].y>y||(g[mid].y==y && g[mid].z>=z))
{
ret=mid;
r=mid-1;
}
else
l=mid+1;
}
if(g[ret].y==y && g[ret].z==z)
return ret;
else
return 0;
}
void calc(int u)
{
int v=u;
long long x=0,y=0,z=0;
for(int i=n+1;i<=m;i++)
{
add(x,y,z,v%3,i);
v/=3;
}
y-=x;
z-=x;
int pos=bs(-y,-z);
if(pos!=0)
if(g[pos].x+x>ans)
{
ans=g[pos].x+x;
choicex=g[pos].choice;
choicey=u;
}
}
void rep(int i,int u)
{
if(i==1)
{
int t=u%3;
if(t==0)
printf("LM\n");
if(t==1)
printf("LW\n");
if(t==2)
printf("MW\n");
return;
}
rep(i-1,u/3);
int t=u%3;
if(t==0)
printf("LM\n");
if(t==1)
printf("LW\n");
if(t==2)
printf("MW\n");
}
void p(int i,int u)
{
while(i<=m)
{
int t=u%3;
u/=3;
i++;
if(t==0)
printf("LM\n");
if(t==1)
printf("LW\n");
if(t==2)
printf("MW\n");
}
}
void print(int l,int r)
{
rep(n,l);
p(n+1,r);
}
int main()
{
ans=-1e14;
scanf("%d",&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&s[i].x,&s[i].y,&s[i].z);
if(m%2==0)
n=m/2;
else
n=m/2+1;
for(int i=0;i<ipow(3,n);i++)
add(i);
sort(g+1,g+has+1,cmp);
for(int i=0;i<ipow(3,m-n);i++)
calc(i);
if(ans!=-1e14)
print(choicex,choicey);
else
printf("Impossible\n");
return 0;
}