Codeforces 585D Lizard Era: Beginning
题意就是
有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; }