HDU 6511 - Min-Max(思维+状压)
题意:HDU6511 - 2019中山大学程序设计竞赛
思路:https://blog.csdn.net/jack_jxnu/article/details/89425942
到位了
1 bool a[1<<16][16]; 2 ll fac[16]; 3 bool b[1001]; 4 int n,m; 5 struct op{ 6 bool oper,flagx,flagy;//oper表示是否max,flag表示是否数组a、b, 7 int x,y; 8 }op[1001]; 9 void pre() 10 { 11 memset(a,0,sizeof(a)); 12 int x=1<<n; 13 for(int i=0;i<x;i++) 14 for(int j=1,t=i;j<=n;j++,t>>=1) 15 a[i][j]=t&1; 16 } 17 void getfac() 18 { 19 fac[0]=1; 20 for(int i=1;i<=15;i++) 21 { 22 fac[i]=fac[i-1]*(ll)i; 23 } 24 } 25 bool Find(int i) //对a[i]数组做模拟运算 26 { 27 for(int j=1;j<=m;j++) 28 { 29 if(op[j].oper) 30 { 31 if(op[j].flagx&&op[j].flagy) b[j]=max(a[i][op[j].x],a[i][op[j].y]); 32 else if(op[j].flagx&&!op[j].flagy) b[j]=max(a[i][op[j].x],b[op[j].y]); 33 else if(!op[j].flagx&&!op[j].flagy) b[j]=max(b[op[j].x],b[op[j].y]); 34 else b[j]=max(b[op[j].x],a[i][op[j].y]); 35 } 36 else 37 { 38 if(op[j].flagx&&op[j].flagy) b[j]=min(a[i][op[j].x],a[i][op[j].y]); 39 else if(op[j].flagx&&!op[j].flagy) b[j]=min(a[i][op[j].x],b[op[j].y]); 40 else if(!op[j].flagx&&!op[j].flagy) b[j]=min(b[op[j].x],b[op[j].y]); 41 else b[j]=min(b[op[j].x],a[i][op[j].y]); 42 } 43 } 44 return b[m]; 45 } 46 int getnum(int i) 47 { 48 int ans=0; 49 for(int j=1;j<=n;j++) 50 if(a[i][j]) ans++; 51 return ans; 52 } 53 int main() 54 { 55 string str; 56 char x,y; 57 int p,q; 58 getfac(); 59 while(scanf("%d%d",&n,&m)!=EOF) 60 { 61 pre(); 62 ll ans=0; 63 for(int i=1;i<=m;i++) 64 { 65 cin>>str>>x>>p>>y>>q; 66 if(str=="max") op[i].oper=1; 67 else op[i].oper=0; 68 if(x=='a') op[i].flagx=1; 69 else op[i].flagx=0; 70 if(y=='a') op[i].flagy=1; 71 else op[i].flagy=0; 72 op[i].x=p;op[i].y=q; 73 } 74 for(int i=0;i<(1<<n);i++) 75 { 76 if(Find(i)) 77 { 78 int cnt=getnum(i); 79 ans+=fac[cnt]*fac[n-cnt]; 80 } 81 } 82 cout<<ans<<endl; 83 } 84 return 0; 85 }