省选模拟赛 LYK loves graph(graph)
题目描述
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)的更多相关文章
- 省选模拟赛 LYK loves rabbits(rabbits)
题目描述 LYK喜欢兔子,它在家中养了3只兔子. 有一天,兔子不堪寂寞玩起了游戏,3只兔子排成一排,分别站在a,b,c这3个位置. 游戏的规则是这样的,重复以下步骤k次:选择两个不同的兔子A和B,假如 ...
- 省选模拟赛 LYK loves string(string)
题目描述 LYK喜欢字符串,它认为一个长度为n的字符串一定会有n*(n+1)/2个子串,但是这些子串是不一定全部都不同的,也就是说,不相同的子串可能没有那么多个.LYK认为,两个字符串不同当且仅当它们 ...
- 【洛谷比赛】[LnOI2019]长脖子鹿省选模拟赛 T1 题解
今天是[LnOI2019]长脖子鹿省选模拟赛的时间,小编表示考的不怎么样,改了半天也只会改第一题,那也先呈上题解吧. T1:P5248 [LnOI2019SP]快速多项式变换(FPT) 一看这题就很手 ...
- @省选模拟赛03/16 - T3@ 超级树
目录 @description@ @solution@ @accepted code@ @details@ @description@ 一棵 k-超级树(k-SuperTree) 可按如下方法得到:取 ...
- 3.28 省选模拟赛 染色 LCT+线段树
发现和SDOI2017树点涂色差不多 但是当时这道题模拟赛的时候不会写 赛后也没及时订正 所以这场模拟赛的这道题虽然秒想到了LCT和线段树但是最终还是只是打了暴力. 痛定思痛 还是要把这道题给补了. ...
- NOI2016模拟赛Zbox loves stack
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...
- [noi.ac省选模拟赛]第12场题解集合
题目 比赛界面. T1 数据范围明示直接\(O(n^2)\)计算,问题就在如何快速计算. 树上路径统计通常会用到差分方法.这里有两棵树,因此我们可以做"差分套差分",在 A 树上对 ...
- [noi.ac省选模拟赛]第11场题解集合
题目 比赛界面. T1 比较简单.容易想到是求鱼竿的最大独立集.由于题目的鱼竿可以被分割为二分图,就可以想到最大匹配. 尝试建边之后会发现边的数量不小,但联系题目性质会发现对于一条鱼竿,它 ...
- 省选模拟赛第四轮 B——O(n^4)->O(n^3)->O(n^2)
一 稍微转化一下,就是找所有和原树差距不超过k的不同构树的个数 一个挺trick的想法是: 由于矩阵树定理的行列式的值是把邻接矩阵数值看做边权的图的所有生成树的边权乘积之和 那么如果把不存在于原树中的 ...
随机推荐
- http-equiv=mobile-agent说明
Meta声明的格式:<meta http-equiv=”mobile-agent” content=”format=[wml|xhtml|html5]; url=url”> 比如: < ...
- SQL语句--连接查询
一.连接查询有以下几种 1.内连接查询 select * from t1 inner join t2 on t1.x = t2.x; 返回有关联的行 2.外链接查询 以下写法都省略了 中间的 out ...
- Zabbix自动发现之fping
原文发表于cu:2016-06-21 Zabbix自动发现功能从配置流程上比较简单:Discovery与Action. 在做Zabbix的自动发现验证时,使用"ICMP ping" ...
- hdu - 6281,2018CCPC湖南全国邀请赛F题,快排
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6281 题意: 根据已给出的式子,进行排序,然后输出排完序后原先的下表. 题解:用结构体保存,在用结构体 ...
- New begin
Purpose 今天更换了id,希望重新沉淀. 晚上看到国外一个博客,落款有个中文: 敬惜字纸. 共勉.
- centos7.2 apache开启.htaccess
打开httpd.conf(在那里? APACHE目录的CONF目录里面),用文本编纂器打开后,查找 (1) AllowOverride None 改为 AllowOverride All (2)去掉下 ...
- TP框架代码学习 学习记录 3.2.3
文件:think.class.php PHP提供register_shutdown_function()这个函数,能够在脚本终止前回调注册的函数,也就是当 PHP 程序执行完成后执行的函数.regis ...
- Scrum立会报告+燃尽图(十月十七日总第八次):分配Alpha阶段任务
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2246 项目地址:https://git.coding.net/zhang ...
- 第五周PSP作业
PSP表格: 累积进度条: 折线图: 饼状图:
- DataGridView,Dataset,DataTable,DataRow等使用心得
DataGridView的列编辑: Name:用于调用属性的时候用的,也可以不使用Name去调用,选择数字1,2,3...选择第1列,第2列,第3列. HeaderText:表头显示的名字方便用户使用 ...