【THUSC2017】巧克力

题目描述

​“人生就像一盒巧克力,你永远不知道吃到的下一块是什么味道。”

​ 明明收到了一大块巧克力,里面有若干小块,排成nm列。每一小块都有自己特别的图案ci,j,它们有的是海星,有的是贝壳,有的是海螺......其中还有一些因为挤压,已经分辨不出是什么图案了。明明给每一小块巧克力标上了一个美味值ai,j ( 0ai,j106 ),这个值越大,表示这一小块巧克力越美味。

​正当明明咽了咽口水,准备享用美味时,舟舟神奇地出现了。看到舟舟恳求的目光,明明决定从中选出一些小块与舟舟一同分享。

​舟舟希望这些被选出的巧克力是连通的(两块巧克力连通当且仅当他们有公共边),而且这些巧克力要包含至少k ( 1k5 )种。而那些被挤压过的巧克力则是不能被选中的。

​ 明明想满足舟舟的愿望,但他又有点“抠”,想将美味尽可能多地留给自己。所以明明希望选出的巧克力块数能够尽可能地少。如果在选出的块数最少的前提下,美味值的中位数(我们定义n个数的中位数为第n+12小的数)能够达到最小就更好了。

​ 你能帮帮明明吗?

输入格式

从标准输入读入数据。

​ 每个测试点包含多组测试数据。

​ 输入第一行包含一个正整数 T (1T5),表示测试数据组数。

​ 对于每组测试数据:

​ 输入第一行包含三个正整数n,mk

​ 接下来n行,每行m个整数,表示每小块的图案ci,j。若ci,j=1表示这一小块受到过挤压,不能被选中;

​ 接下来n行,每行m个整数,表示每个小块的美味值ai,j

输出格式

输出到标准输出。

​ 输出共包括T行,每行包含两个整数,用空格隔开,即最少的块数和最小的美味值中位数。

​ 若对于某组测试数据,不存在任意一种合法的选取方案,请在对应行输出两个1

数据范围 n×m233 ci,j=11ci,jn×m


 

 

 题解:

    • 二分一个出现过的美味度做中位数,将$a_{ij}$大于中位树的设为$1001$,小于的设为$999$,等于的设为$1000$
    • 在满足条件下取尽量小的代价和就做到了个数做第一关键字,中位数做第二关键字;
    • 将颜色在$0-k$内随机一个新颜色,考虑$0-k$全都取就取了$k$种,多随机几次;
    • 每次斯坦纳树求出最小代价;
    • $spfa$算满的话是:$O(T* t *(nm \ 3^{k} + (nm)^2 \ 2^k) )$;
    • 感觉整个题充满了脑洞。。。。
    •  1 #include<bits/stdc++.h>
       2 #define inf 0x3f3f3f3f
       3 #define fir first
       4 #define sec second 
       5 #define mk make_pair
       6 using namespace std;
       7 const int N=250;
       8 int n,m,k,a[N][N],c[N][N],sub[N],tot,f[N][N][1<<5],id[N][N],col[N],b[N][N],ans1,ans2,vis[N][N];
       9 typedef pair<int,int>pii;
      10 queue<pii>q;
      11 int dx[4]={0,0,1,-1};
      12 int dy[4]={1,-1,0,0}; 
      13 void spfa(int s){
      14     while(!q.empty()){
      15         int x=q.front().fir, y=q.front().sec;
      16         q.pop();vis[x][y]=0;
      17         for(int i=0;i<4;i++){
      18             int nx=x+dx[i], ny=y+dy[i];
      19             if(nx<1||nx>n||ny<1||ny>m||!~c[nx][ny])continue;
      20             if(f[nx][ny][s] > f[x][y][s] + b[nx][ny]){
      21                 f[nx][ny][s] = f[x][y][s] + b[nx][ny];
      22                 if(!vis[nx][ny])vis[nx][ny]=1,q.push(mk(nx,ny));
      23             }
      24         }
      25     }
      26 }
      27 void steiner(){
      28     for(int i=1;i<=n;i++)
      29     for(int j=1;j<=m;j++){
      30         for(int s=0;s<1<<k;s++)f[i][j][s]=inf;
      31         if(~c[i][j])f[i][j][1<<col[c[i][j]]]=b[i][j];
      32     }
      33     for(int s=1;s<1<<k;s++){
      34         for(int i=1;i<=n;i++)
      35         for(int j=1;j<=m;j++)if(~c[i][j]){
      36             for(int t=s&(s-1);t;t=s&(t-1)){
      37                 f[i][j][s] = min(f[i][j][s], f[i][j][t] + f[i][j][s^t] - b[i][j]);
      38             }
      39             if(f[i][j][s]!=inf)q.push(mk(i,j)),vis[i][j]=1;
      40         }
      41         spfa(s);
      42     }
      43     for(int i=1;i<=n;i++)
      44     for(int j=1;j<=m;j++)ans1 = min(ans1, f[i][j][(1<<k)-1]);
      45 }
      46 int main(){
      47     freopen("T1.in","r",stdin);
      48     freopen("T1.out","w",stdout);
      49     srand(time(NULL));
      50     int T;scanf("%d",&T);
      51     while(T--){
      52         scanf("%d%d%d",&n,&m,&k);
      53         tot=0;
      54         for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%d",&c[i][j]);
      55         for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%d",&a[i][j]),sub[id[i][j]=++tot]=a[i][j];
      56         sort(sub+1,sub+tot+1);
      57         tot = unique(sub+1,sub+tot+1) - sub - 1;
      58         int l=1,r=tot;
      59         while(l<r){
      60             int mid=(l+r)>>1;
      61             for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)b[i][j]=a[i][j]>sub[mid]?1001:a[i][j]<mid?999:1000;
      62             ans1 = inf;
      63             for(int I=1;I<=200;I++){
      64                 for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)col[id[i][j]]=rand()%k;
      65                 steiner();
      66             }
      67             ans2 = (ans1+500) / 1000;
      68             if(ans1 <= ans2 * 1000)r=mid;
      69             else l=mid+1;
      70         }
      71         if(ans1==inf)puts("-1 -1"); 
      72         printf("%d %d\n",ans2,sub[l]);
      73     }
      74     return 0;
      75 }
      THUSC2017D1T1

猜你喜欢

转载自www.cnblogs.com/Paul-Guderian/p/10246851.html