UVA 10159
http://blog.csdn.net/metaphysis/article/details/6926997
先向作者表达一下敬佩吧,十分巧妙地利用了状态压缩。
这道题有点组合数学的味道,当一个格子选后,就把行最大值与格子值相等的行标志位置1.这样,当111111111111即是求的状态了。
这样,可以设一个sum[MAX-1]的数组来对应每一种状态,通过位的或运算的关系来实现状态转移。实在妙极。
原作者代码:
// [解题方法]
// 根据每个小格所属行的限制来确定该小格内的最大值,然后检测是否满足每行的最大值要求,若不满足,则
// 不可能,若满足,求其最大值。对于最小可能值,可以通过动态规划来获得。 #include <iostream>
#include <cstring>
#include <sstream> using namespace std; #define MAXLINES 12 // 行数。
#define MAXCELLS 48 // 小格总个数。
#define MAXINT 10
#define EMPTY (-1)
#define MAXTYPES (1 << 12) int maxValue[MAXLINES]; // 每行的最大值。
int cells[MAXCELLS]; // 小格内数字值。 // 每个小格属于那些行,行使用题目所给的 A - I 表示。从 0 开始,按从上到下,从左至右的顺序编号。
string belongs[MAXCELLS] = {
"EL", //
"EK", "EL", "FL", // 1 - 3
"AI", "AI", "AJ", "AEJ", "AEK", "AFK", "AFL", "AGL", "AG", "AH", "AH", // 4 - 14
"BI", "BEI", "BEJ", "BFJ", "BFK", "BGK", "BGL", "BHL", "BH", // 15 - 23
"CE", "CEI", "CFI", "CFJ", "CGJ", "CGK", "CHK", "CHL", "CL", // 24 - 32
"DE", "DE", "DF", "DFI", "DGI", "DGJ", "DHJ", "DHK", "DK", "DL", "DL", // 33 - 43
"GI", "HI", "HJ", // 44 - 46
"HI" //
}; // 非 EMPTY 元素值表示组成该行的小格编号,从 0 开始,按从上到下,从左至右的顺序编号。
int lines[MAXLINES][MAXLINES - ] = {
{ , , , , , , , , , , },
{ , , , , , , , , , EMPTY, EMPTY },
{ , , , , , , , , , EMPTY, EMPTY },
{ , , , , , , , , , , },
{ , , , , , , , , , , },
{ , , , , , , , , , EMPTY, EMPTY },
{ , , , , , , , , , EMPTY, EMPTY },
{ , , , , , , , , , , },
{ , , , , , , , , , , },
{ , , , , , , , , , EMPTY, EMPTY },
{ , , , , , , , , , EMPTY, EMPTY },
{ , , , , , , , , , , }
}; // 动态规划求最小可能值,这里使用了 tmp
// 数组,在原 sum 数组计算的结果先填写在 tmp 数组上,以免持续在 sum 数组上操作引起混乱,同时
// 注意最小可能值方案一定是将最大可能值方案中某些小格置 0 而得来的(为什么这样,可以思考一下!)。
int dynamic_programming()
{
int sum[MAXTYPES], tmp[MAXTYPES]; // 初始化。
memset(sum, EMPTY, sizeof(sum)); // 当无任何行匹配时,和最小值为 0.
sum[] = ; for (int i = ; i < MAXLINES; i++)
{
// 在副本上操作。
memcpy(tmp, sum, sizeof(sum));
for (int j = ; j < MAXTYPES; j++)
if (sum[j] > EMPTY)
{
for (int k = ; k < MAXLINES - ; k++)
{
// 空小格,该行已处理完毕。
if (lines[i][k] == EMPTY)
break; // 只需处理值为该行最大值的小格。
if (cells[lines[i][k]] == maxValue[i])
{
int t = j;
// cell 表示该小格属于哪些行。
string cell = belongs[lines[i][k]];
for (int c = ; c < cell.length(); c++)
// 注意条件!只有当小格的值满足了某行的最大值要求,才计
// 入 t。t 的意义是该小格值满足了哪些行的最大值要求。
// 使用匹配的行的序号作为移位值来生成一个唯一表示该行的
// 整数。
if (cells[lines[i][k]] == maxValue[cell[c] - 'A'])
t = t | ( << (cell[c] - 'A')); // 更新和的最小值。
if (tmp[t] > EMPTY)
tmp[t] = min(tmp[t], sum[j] + maxValue[i]);
else
tmp[t] = sum[j] + maxValue[i];
}
}
} // 获得副本上的结果。
memcpy(sum, tmp, sizeof(tmp));
} return sum[MAXTYPES - ];
} int main(int ac, char *av[])
{
string line; while (getline(cin, line))
{
// 读入每行的最大值限制。
istringstream iss(line);
for (int i = ; i < MAXLINES; i++)
iss >> maxValue[i]; // 根据限制,获得每个方格的最大值。
memset(cells, , sizeof(cells));
for (int i = ; i < MAXCELLS; i++)
{
int value = MAXINT;
for (int j = ; j < belongs[i].length(); j++)
value = min(value,
maxValue[belongs[i][j] - 'A']); cells[i] = value;
} // 检查方格的值是否满足最大值要求。
bool noSolution = false;
for (int i = ; i < MAXLINES; i++)
{
int tmp = ;
for (int j = ; j < MAXLINES - ; j++)
{
if (lines[i][j] == EMPTY)
break;
tmp = max(tmp, cells[lines[i][j]]);
} if (tmp != maxValue[i])
{
noSolution = true;
break;
}
} // 输出。
if (noSolution)
cout << "NO SOLUTION" << endl;
else
{
// 数字和最大可能值。
int maxSum = ;
for (int i = ; i < MAXCELLS; i++)
maxSum += cells[i]; // 数字和最小可能值。最小可能值的含义是取尽可能少的数字,使得满足所有
// 最大值的要求。由于前面的最大可能值方案中已经包含了最小可能值的方案,
// 需要将一些小格置为 0 来获得最小可能值,如果小格置 0 的数目越多,
// 当然最后和更小,那么就要求一个小格的数字尽可能满足多行的最大值要求,
// 这样可以减少非零数字的使用,可以使用动态规划找最小值。
int minSum = dynamic_programming(); cout << minSum << " " << maxSum << endl;
}
} return ;
}
可怜不知为什么,我的代码竟没能AC。算了,领悟到这样绝妙的思想,已经很满足了。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <sstream> #define EMPTY (-1)
#define MAXLINES 12 // 行数。
#define MAXCELLS 48 // 小格总个数。
#define MAXLEN (1<<12) using namespace std; int lines[MAXLINES][MAXLINES - ] = {
{ , , , , , , , , , , },
{ , , , , , , , , , EMPTY, EMPTY },
{ , , , , , , , , , EMPTY, EMPTY },
{ , , , , , , , , , , },
{ , , , , , , , , , , },
{ , , , , , , , , , EMPTY, EMPTY },
{ , , , , , , , , , EMPTY, EMPTY },
{ , , , , , , , , , , },
{ , , , , , , , , , , },
{ , , , , , , , , , EMPTY, EMPTY },
{ , , , , , , , , , EMPTY, EMPTY },
{ , , , , , , , , , , }
}; string belongs[MAXCELLS] = {
"EL", // 0
"EK", "EL", "FL", // 1 - 3
"AI", "AI", "AJ", "AEJ", "AEK", "AFK", "AFL", "AGL", "AG", "AH", "AH", // 4 - 14
"BI", "BEI", "BEJ", "BFJ", "BFK", "BGK", "BGL", "BHL", "BH", // 15 - 23
"CE", "CEI", "CFI", "CFJ", "CGJ", "CGK", "CHK", "CHL", "CL", // 24 - 32
"DE", "DE", "DF", "DFI", "DGI", "DGJ", "DHJ", "DHK", "DK", "DL", "DL", // 33 - 43
"GI", "HI", "HJ", // 44 - 46
"HI" // 47
}; int maze[];
int maxtype[],tes[];
int sum[MAXLEN],tmp[MAXLEN]; int dp(){
memset(sum,-,sizeof(sum));
sum[]=;
for(int i=;i<;i++){
memcpy(tmp, sum, sizeof(sum));
for(int k=;k<MAXLEN;k++){
if(sum[k]==-)
continue;
for(int p=;lines[i][p]!=EMPTY&&p<MAXLINES-;p++){
// if(maze[lines[i][p]]!=maxtype[i]) continue;
int t=k;
for(int q=;q<belongs[lines[i][p]].length();q++){
if(maze[lines[i][p]]==maxtype[belongs[lines[i][p]][q]-'A'])
t=t|(<<(belongs[lines[i][p]][q]-'A'));
}
if(tmp[t]==-){
tmp[t]=sum[k]+maxtype[i];
}
else {
tmp[t]=min(tmp[t],sum[k]+maxtype[i]);
}
}
}
memcpy(sum, tmp, sizeof(tmp));
// cout<<maxtype[i]<<endl;
}
return sum[MAXLEN-];
} int main(){
string line; while (getline(cin, line))
{
// 读入每行的最大值限制。
istringstream iss(line);
for (int i = ; i < MAXLINES; i++)
iss >> maxtype[i];
memset(tes,-,sizeof(tes));
for(int i=;i<;i++)
maze[i]=;
int ans=;
for(int i=;i<;i++){
for(int k=;k<belongs[i].length();k++){
maze[i]=min(maze[i],maxtype[belongs[i][k]-'A']);
}
for(int k=;k<belongs[i].length();k++)
tes[belongs[i][k]-'A']=max(maze[i],tes[belongs[i][k]-'A']);
ans+=maze[i];
}
bool flag=true;
for(int i=;i<;i++)
if(tes[i]!=maxtype[i]){
flag=false;
break;
}
if(!flag){
cout<<"NO SOLUTION"<<endl;
continue;
}
int res=dp();
cout<<res<<' '<<ans<<endl;
}
return ;
}
UVA 10159的更多相关文章
- uva 1354 Mobile Computing ——yhx
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABGcAAANuCAYAAAC7f2QuAAAgAElEQVR4nOy9XUhjWbo3vu72RRgkF5
- UVA 10564 Paths through the Hourglass[DP 打印]
UVA - 10564 Paths through the Hourglass 题意: 要求从第一层走到最下面一层,只能往左下或右下走 问有多少条路径之和刚好等于S? 如果有的话,输出字典序最小的路径 ...
- UVA 11404 Palindromic Subsequence[DP LCS 打印]
UVA - 11404 Palindromic Subsequence 题意:一个字符串,删去0个或多个字符,输出字典序最小且最长的回文字符串 不要求路径区间DP都可以做 然而要字典序最小 倒过来求L ...
- UVA&&POJ离散概率与数学期望入门练习[4]
POJ3869 Headshot 题意:给出左轮手枪的子弹序列,打了一枪没子弹,要使下一枪也没子弹概率最大应该rotate还是shoot 条件概率,|00|/(|00|+|01|)和|0|/n谁大的问 ...
- UVA计数方法练习[3]
UVA - 11538 Chess Queen 题意:n*m放置两个互相攻击的后的方案数 分开讨论行 列 两条对角线 一个求和式 可以化简后计算 // // main.cpp // uva11538 ...
- UVA数学入门训练Round1[6]
UVA - 11388 GCD LCM 题意:输入g和l,找到a和b,gcd(a,b)=g,lacm(a,b)=l,a<b且a最小 g不能整除l时无解,否则一定g,l最小 #include &l ...
- UVA - 1625 Color Length[序列DP 代价计算技巧]
UVA - 1625 Color Length 白书 很明显f[i][j]表示第一个取到i第二个取到j的代价 问题在于代价的计算,并不知道每种颜色的开始和结束 和模拟赛那道环形DP很想,计算这 ...
- UVA - 10375 Choose and divide[唯一分解定理]
UVA - 10375 Choose and divide Choose and divide Time Limit: 1000MS Memory Limit: 65536K Total Subm ...
- UVA - 11584 Partitioning by Palindromes[序列DP]
UVA - 11584 Partitioning by Palindromes We say a sequence of char- acters is a palindrome if it is t ...
随机推荐
- bzoj 4481 [ Jsoi 2015 ] 非诚勿扰 —— 期望
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4481 太弱了这种题都要看半天TJ...:https://blog.csdn.net/chai ...
- PCB MongoDB 数据库 Collection集合导出与导入
由于一直以来用微软可视化图形界面习惯了,而MongoDB是命令式操作,而用系统自带CMD操作不方便, 这里介绍一款CMD的替代品,大小100多M. Cmder工具下载 https://github. ...
- git 设定全局ignore
创建: 2017/08/08 位置: $HOME/.config/git/ignore git/ignore 要自建 内容 https://github.com/github/gitignore ...
- centos安装lamp步骤还可以
1. 用yum安装Apache,Mysql,PHP. 1.1安装Apache yum install httpd httpd-devel 安装完成后,用/etc/init.d/httpd start ...
- Java 位运算符 &、|、^、~、<<、>>、>>>
撸了N久的代码,但是突然冒出来个位运算,我就蒙蔽了,这是什么?我是谁?我在干什么?我在哪? 1)闲扯 关于位运算符无非也就 与(&).或(|).异或(^).取反(~).左移(<< ...
- python 8:list.sort(reverse=false)、sorted(list, reverse=false)(对列表进行不可恢复排序;对列表进行可恢复排序)
bicycles = ['trek', 'cannondale', 'redline', 'specialized'] print(bicycles) print(sorted(bicycles)) ...
- ROS-URDF-Xacro
前言:Xacro是一种宏语言,允许代码复用,使用Xacro可以减少URDF文件中的代码量. 参考自:http://wiki.ros.org/urdf/Tutorials/Using%20Xacro%2 ...
- 【HTTP】如何正常关闭连接
参考:<HTTP权威指南> 所有HTTP客户端.服务器或者代理都可以任意时刻关闭一条TCP传输连接.但是服务器永远无法确定它关闭“空闲”连接的那一刻,在线路那一头的客户端有没有数据要发送. ...
- swift 类型系统 Self self Type
namedClass:静态类型:与类型实现直接关联:可以用于初始化.类型检查等. namedClass.self:@thick,脱敏(脱关)类型:动态类型:可以作为元类型的实例:可以作为类型参量进行传 ...
- Redis 通用key操作命令
1.在redis里面允许模糊查询key,有3个通配符:*,?,[]. *:通配任意字符 ?:通配单个字符 []:通配中括号内的某个字符 例如: 2.randomKey 随机返回所有key中的某个 3. ...