题目描述

LYK喜欢花花绿绿的图片,有一天它得到了一张彩色图片,这张图片可以看做是一张n*m的网格图,每个格子都有一种颜色去染着,我们用-1至n*m-1来表示一个格子的颜色。特别地,-1代表这个颜色是黑色,LYK不喜欢黑色!

LYK想将剪下这张图片中的一张子图片来(四联通块),使得这个子图片不存在黑色的格子,并且至少有k个不同的颜色。

但是每个格子有自己的脾气,特别的,第i行第j列这个格子如果被LYK选中了,LYK需要花费相应的代价。LYK想花费尽可能少的代价来剪下一张满足自己要求的图片。

输入格式(graph.in)

第一行三个整数,n,m,k.

接下来n行,每行m个数,表示图片中每个格子的颜色,每个数在-1到n*m-1之间。

 接下来n行,每行m个数,表示选择每个位置所需要的代价。

输出格式(graph.out)

一行,表示最小代价和。

输入样例

3 3 3

0 0 1

2 3 3

-1 2 1

3 1 5

4 10 1

9 3 4

输出样例

7

数据范围

对于20%的数据:1<=n,m,k<=4。

对于另外30%的数据:不同的颜色数<=10(不包括-1)。

对于再另外30%的数据:1<=n<=2,1<=m<=15。

对于100%的数据:1<=n,m<=15,1<=k<=7,1<=ai,j<=100000。

数据保证一定有解。

分析:对于前50%的数据,就是一个裸的斯坦纳树. 剩下50%的数据因为颜色数太多,状态表示不下.

   注意到k 还是≤7,也就是我们只关注7个不同的颜色. 利用概率性算法,将所有的颜色随机映射到k种颜色中,然后利用前50%的数据的算法. 做一次的成功率是非常低的,多做几次就好了.

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; const int inf = 0x7ffffff;
const int dx[] = {,,,-},dy[] = {,-,,}; int n,m,k,ans = inf,tot,maxx,block,who,maxn;
int col[][],a[][],flag[][];
int vis[],bb[],f[][][],g[],vis2[][];
bool can[][];
int b[],cnt,Time = ,pos[]; struct node
{
int x,y;
}; void spfa(int sta)
{
queue <node> q;
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
{
if (col[i][j] != -)
{
node temp;
temp.x = i;
temp.y = j;
q.push(temp);
vis2[i][j] = ;
}
}
while (!q.empty())
{
node u = q.front();
q.pop();
int x = u.x,y = u.y;
vis2[x][y] = ;
for (int i = ; i < ; i++)
{
int nx = x + dx[i],ny = y + dy[i];
if (nx >= && nx <= n && ny >= && ny <= m && col[nx][ny] != -)
{
if (f[nx][ny][sta] > f[x][y][sta] + a[nx][ny])
{
f[nx][ny][sta] = f[x][y][sta] + a[nx][ny];
if (!vis2[nx][ny])
{
vis2[nx][ny] = ;
node temp;
temp.x = nx;
temp.y = ny;
q.push(temp);
}
}
}
}
}
} bool check2(int x)
{
int res = ;
while (x)
{
if (x & )
res++;
x >>= ;
}
if (res >= k)
return true;
return false;
} void solve2()
{
tot = ;
memset(vis,,sizeof(vis));
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
{
if (col[i][j] != -)
{
if (!vis[col[i][j]])
{
bb[col[i][j]] = ++tot;
vis[col[i][j]] = ;
}
}
}
maxx = ( << tot) - ;
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
for (int k = ; k <= maxx; k++)
f[i][j][k] = inf;
for (int k = ; k <= maxx; k++)
g[k] = inf;
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
{
if (col[i][j] != -)
f[i][j][ << (bb[col[i][j]] - )] = a[i][j];
}
for (int i = ; i <= maxx; i++)
{
for (int j = ; j <= n; j++)
for (int k = ; k <= m; k++)
for (int l = i; l; l = (l - ) & i)
f[j][k][i] = min(f[j][k][i],f[j][k][l] + f[j][k][l ^ i] - a[j][k]);
spfa(i);
for (int j = ; j <= n; j++)
for (int k = ; k <= m; k++)
g[i] = min(g[i],f[j][k][i]);
}
for (int i = ; i <= maxx; i++)
if (check2(i))
ans = min(ans,g[i]);
printf("%d\n",ans);
} void spfa2(int sta)
{
memset(vis2,,sizeof(vis2));
queue <node> q;
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
{
if (col[i][j] != -)
{
node temp;
temp.x = i;
temp.y = j;
q.push(temp);
vis2[i][j] = ;
}
}
while (!q.empty())
{
node u = q.front();
q.pop();
int x = u.x,y = u.y;
vis2[x][y] = ;
for (int i = ; i < ; i++)
{
int nx = x + dx[i],ny = y + dy[i];
if (nx >= && nx <= n && ny >= && ny <= m && col[nx][ny] != -)
{
if (f[nx][ny][sta] > f[x][y][sta] + a[nx][ny])
{
f[nx][ny][sta] = f[x][y][sta] + a[nx][ny];
if (!vis2[nx][ny])
{
vis2[nx][ny] = ;
node temp;
temp.x = nx;
temp.y = ny;
q.push(temp);
}
}
}
}
}
} void solve()
{
maxx = ( << ) - ;
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
for (int k = ; k <= maxx; k++)
f[i][j][k] = inf;
for (int k = ; k <= maxx; k++)
g[k] = inf;
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
{
if (col[i][j] != -)
f[i][j][ << (pos[col[i][j]] - )] = a[i][j];
}
for (int i = ; i <= maxx; i++)
{
for (int j = ; j <= n; j++)
for (int k = ; k <= m; k++)
for (int l = i; l; l = (l - ) & i)
f[j][k][i] = min(f[j][k][i],f[j][k][l] + f[j][k][l ^ i] - a[j][k]);
spfa2(i);
for (int j = ; j <= n; j++)
for (int k = ; k <= m; k++)
g[i] = min(g[i],f[j][k][i]);
}
for (int i = ; i <= maxx; i++)
{
if (check2(i))
ans = min(ans,g[i]);
}
} int main()
{ scanf("%d%d%d",&n,&m,&k);
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
{
scanf("%d",&col[i][j]);
if (col[i][j] != -)
b[++cnt] = col[i][j];
}
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
scanf("%d",&a[i][j]);
sort(b + ,b + + cnt);
cnt = unique(b + ,b + + cnt) - b - ;
if (cnt <= )
solve2();
else
{
Time = ;
while (Time--)
{
random_shuffle(b + ,b + + cnt);
for (int i = ; i <= cnt; i++)
pos[b[i]] = ((i - ) % ) + ;
solve();
}
printf(" %d\n",ans);
} return ;
}

省选模拟赛 LYK loves graph(graph)的更多相关文章

  1. 省选模拟赛 LYK loves rabbits(rabbits)

    题目描述 LYK喜欢兔子,它在家中养了3只兔子. 有一天,兔子不堪寂寞玩起了游戏,3只兔子排成一排,分别站在a,b,c这3个位置. 游戏的规则是这样的,重复以下步骤k次:选择两个不同的兔子A和B,假如 ...

  2. 省选模拟赛 LYK loves string(string)

    题目描述 LYK喜欢字符串,它认为一个长度为n的字符串一定会有n*(n+1)/2个子串,但是这些子串是不一定全部都不同的,也就是说,不相同的子串可能没有那么多个.LYK认为,两个字符串不同当且仅当它们 ...

  3. 【洛谷比赛】[LnOI2019]长脖子鹿省选模拟赛 T1 题解

    今天是[LnOI2019]长脖子鹿省选模拟赛的时间,小编表示考的不怎么样,改了半天也只会改第一题,那也先呈上题解吧. T1:P5248 [LnOI2019SP]快速多项式变换(FPT) 一看这题就很手 ...

  4. @省选模拟赛03/16 - T3@ 超级树

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 一棵 k-超级树(k-SuperTree) 可按如下方法得到:取 ...

  5. 3.28 省选模拟赛 染色 LCT+线段树

    发现和SDOI2017树点涂色差不多 但是当时这道题模拟赛的时候不会写 赛后也没及时订正 所以这场模拟赛的这道题虽然秒想到了LCT和线段树但是最终还是只是打了暴力. 痛定思痛 还是要把这道题给补了. ...

  6. NOI2016模拟赛Zbox loves stack

    #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...

  7. [noi.ac省选模拟赛]第12场题解集合

    题目 比赛界面. T1 数据范围明示直接\(O(n^2)\)计算,问题就在如何快速计算. 树上路径统计通常会用到差分方法.这里有两棵树,因此我们可以做"差分套差分",在 A 树上对 ...

  8. [noi.ac省选模拟赛]第11场题解集合

    题目   比赛界面. T1   比较简单.容易想到是求鱼竿的最大独立集.由于题目的鱼竿可以被分割为二分图,就可以想到最大匹配.   尝试建边之后会发现边的数量不小,但联系题目性质会发现对于一条鱼竿,它 ...

  9. 省选模拟赛第四轮 B——O(n^4)->O(n^3)->O(n^2)

    一 稍微转化一下,就是找所有和原树差距不超过k的不同构树的个数 一个挺trick的想法是: 由于矩阵树定理的行列式的值是把邻接矩阵数值看做边权的图的所有生成树的边权乘积之和 那么如果把不存在于原树中的 ...

随机推荐

  1. JY播放器【喜马拉雅FM电脑端,附带下载功能】

    今天给大家带来一款神器----JY播放器.可以不用打开网页就在电脑端听喜马拉雅FM的节目,而且可以直接下载,对于我这种强迫症患者来说真的是神器.我是真的不喜欢电脑任务栏上面密密麻麻的. 目前已经支持平 ...

  2. shell基础 -- 基本语法

    本文介绍一下 shell 的语法. 一.变量 在 shell 里,使用变量之前通常并不需要事先为他们做出声明,需要使用的时候直接创建就行了.默认情况下,所有变量都被看做字符串并以字符串来存储,即使它们 ...

  3. 《Cocos2d-x游戏开发实战精解》学习笔记2--在Cocos2d-x中显示一行文字

    在Cocos2d-x中要显示文字就需要用到Label控件.在3.x版本的Cocos2d中,舍弃了之前版本所使用的LabelTTF.LabelAtlas.LabelBMFont 3个用于显示文字的类,而 ...

  4. [C++基础] 成员变量的初始化顺序

    转载链接:https://blog.csdn.net/qq_37059483/article/details/78608375 1.成员变量在使用初始化列表初始化时,只与定义成员变量的顺序有关,与构造 ...

  5. Windows和Linux系统如何退出python命令行

    python命令行是新手学习python过程中必须要学的一个工具,下面我们来看一下怎么退出python命令行. 第一种方式: 使用python提供的exit()函数,linux平台和windows平台 ...

  6. windows下对python的pip更新到最新版本

    1->打开windows的命令窗口. 2->进入到pip.exe所在的文件夹下,我安装的python在G:\python3.6文件夹下,pip.exe则在G:\python3.6\Scri ...

  7. Erlang/Elixir: 使用 OpenCV, Python 搭建图片缩略图服务器

    这篇文章是在OSX上测试和运行的的, Ubuntu下的安装和配置请移步到这里 应用程序进程树, 默认 Poolboy 中初始化10个用于处理图片的 Python 工作进程(Worker) 首先安装Op ...

  8. erlang调优方法

    1. 来自Scaling Erlang的方法 内核调优: # Increase the ipv4 port range: sysctl -w net.ipv4.ip_local_port_range= ...

  9. JSON:JavaScript 对象表示法

    JSON:JavaScript 对象表示法(JavaScript Object Notation). JSON 是存储和交换文本信息的语法.类似 XML. JSON 比 XML 更小.更快,更易解析. ...

  10. DBGRID控件里可以实现SHIFT复选吗?怎么设置?

    //////////////////////////////////////////////////    功能概述:公用的列表框选择框,是用DBGrid网格////    注意事项:希望用Query ...