zoukankan      html  css  js  c++  java
  • loj2977 巧克力 (斯坦纳树+随机化)

    考虑颜色比较少的时候,第一问可以直接斯坦纳树

    第二问考虑二分,每次把每格的权值给成1000+[a[i]>m],就是在个数最少的基础上尽量选小于等于m的

    然而颜色太多不能直接做,但可以把每种颜色映射到5以内,这样的话,做一次的正确率就是作为答案的那5种颜色分别被映射到了1~5的概率,就是$frac{5!}{5^5}=0.0384$,做233次正确率就有$99.989\%$了

     1 #include<bits/stdc++.h>
     2 #include<tr1/unordered_map>
     3 #define CLR(a,x) memset(a,x,sizeof(a))
     4 #define MP make_pair
     5 #define fi first
     6 #define se second
     7 using namespace std;
     8 typedef long long ll;
     9 typedef unsigned long long ull;
    10 typedef long double ld;
    11 typedef pair<int,int> pa;
    12 const int maxn=250,maxp=50;
    13 
    14 inline ll rd(){
    15     ll x=0;char c=getchar();int neg=1;
    16     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
    17     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    18     return x*neg;
    19 }
    20 
    21 int step[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
    22 int id[maxn][maxn],pct,pos[maxn][2];
    23 int N,M,S,K;
    24 int f[maxn][maxp],c[maxn],a[maxn],val[maxn];
    25 int hsh[maxn],C;
    26 
    27 queue<int> q;
    28 bool flag[maxn];
    29 inline void spfa(int s){
    30     for(int i=1;i<=pct;i++) if(c[i]!=-1) flag[i]=1,q.push(i);
    31     
    32     while(!q.empty()){
    33         int p=q.front();q.pop();
    34         flag[p]=0;
    35         int x=pos[p][0],y=pos[p][1];
    36         for(int j=0;j<4;j++){
    37             int nx=x+step[j][0],ny=y+step[j][1];
    38             if(nx<1||ny<1||nx>N||ny>M||c[id[nx][ny]]==-1) continue;
    39             int ni=id[nx][ny];
    40             if(f[ni][s]>f[p][s]+val[ni]){
    41                 f[ni][s]=f[p][s]+val[ni];
    42                 if(!flag[ni]) q.push(ni),flag[ni]=1;
    43             }
    44         }
    45     }
    46 }
    47 
    48 inline int solve(){
    49     CLR(f,63);
    50     for(int i=1;i<=pct;i++) if(c[i]!=-1) f[i][1<<hsh[c[i]]]=val[i];
    51     for(int s=1;s<(1<<K);s++){
    52         for(int i=1;i<=pct;i++){
    53             if(c[i]==-1) continue;
    54             for(int ss=(s-1)&s;ss;ss=(ss-1)&s){
    55                 f[i][s]=min(f[i][s],f[i][ss]+f[i][s^ss]-val[i]);
    56             }
    57         }
    58         spfa(s);
    59     }
    60     int ans=1e9;
    61     for(int i=1;i<=pct;i++) ans=min(ans,f[i][(1<<K)-1]);
    62     return ans;
    63 }
    64 
    65 int main(){
    66     //freopen("","r",stdin);
    67     srand(19260817);
    68     for(int T=rd();T;T--){
    69         pct=0,C=0;
    70         N=rd(),M=rd(),K=rd();
    71         for(int i=1;i<=N;i++){
    72             for(int j=1;j<=M;j++) id[i][j]=++pct,pos[pct][0]=i,pos[pct][1]=j;
    73         }
    74         for(int i=1;i<=N;i++) for(int j=1;j<=M;j++) c[id[i][j]]=rd(),C=max(C,c[id[i][j]]);
    75         for(int i=1;i<=N;i++) for(int j=1;j<=M;j++) a[id[i][j]]=rd();
    76         int ans1=1e9,ans2=1e9;
    77         for(int t=1;t<=233;t++){
    78             for(int i=1;i<=C;i++) hsh[i]=rand()%K;
    79             int l=0,r=1e6,a1=1e9,a2=1e9;
    80             while(l<=r){
    81                 int m=(l+r)>>1;
    82                 for(int i=1;i<=pct;i++) val[i]=(c[i]==-1?1e8:1000+(a[i]>m));
    83                 int re=solve();
    84                 if(re>=1e8) break;
    85                 a1=re/1000;
    86                 int x=a1-(re-a1*1000);
    87                 if(x>=(a1+1)/2) a2=m,r=m-1;
    88                 else l=m+1;
    89             }
    90             if(a1<ans1||(ans1==a1&&a2<=ans2)) ans1=a1,ans2=a2;
    91         }
    92         
    93         printf("%d %d
    ",ans1==1e9?-1:ans1,ans1==1e9?-1:ans2);
    94     }
    95     return 0;
    96 }
  • 相关阅读:
    Win7+Centos7双系统安装/树莓派安装Centos7
    C++学习笔记
    Ubuntu Codeblocks配置Eigen Sophus
    Java笔记
    解决Mac下AndroidStudio内容时卡顿
    解决Android RadioGroup跑到输入法上面
    Activity去掉标题不成功的解决方法
    Synergy屏幕共享键鼠 (for Mac&Ubuntu)
    Android 限制控件多次点击
    Bitmap 创建、转换、圆角、设置透明度
  • 原文地址:https://www.cnblogs.com/Ressed/p/10613569.html
Copyright © 2011-2022 走看看