poj 1191 棋盘分割 dp-进阶
来源:互联网 发布:linux命令大全 编辑:程序博客网 时间:2024/05/03 19:58
棋盘分割
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 14272Accepted: 5107
Description
将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘。(每次切割都只能沿着棋盘格子的边进行)
原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和。现在需要把棋盘按上述规则分割成n块矩形棋盘,并使各矩形棋盘总分的均方差最小。
均方差,其中平均值,xi为第i块矩形棋盘的总分。
请编程对给出的棋盘及n,求出O'的最小值。
Input
第1行为一个整数n(1 < n < 15)。
第2行至第9行每行为8个小于100的非负整数,表示棋盘上相应格子的分值。每行相邻两数之间用一个空格分隔。
Output
仅一个数,为O'(四舍五入精确到小数点后三位)。
Sample Input
3
1 1 1 1 1 1 1 3
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 0
1 1 1 1 1 1 0 3
Sample Output
1.633
Source
Noi 99
一:横着切,当前矩形将会分成上下两份1.选上面:dp[k][x1][y1][x2][y2]=s[x1][y1][x][y2]+dp[k-1][x+1][y1][x2][y2];2.选下面:dp[k][x1][y1][x2][y2]=s[x+1][y1][x2][y2]+dp[k-1][x1][y1][x][y2];x1<=x<x2二:竖着切,当前矩形将会分成左右两份1.选左边:dp[k][x1][y1][x2][y2]=s[x1][y1][x2][y]+dp[k-1][x1][y+1][x2][y2];2.选右边:dp[k][x1][y1][x2][y2]=s[x1][y+1][x2][y2]+dp[k-1][x1][y1][x2][y];
一:用动态规划
代码:
#include <iostream>#include <cstring>#include <cstdio>#include <cmath>#define maxn 16const short M = 8;using namespace std;double dp[maxn][M][M][M][M], x;int a[M][M], n;double sub(int x1, int y1, int x2, int y2) { double s; s =a[x2][y2]; if (x1 != 0) s -= a[x1-1][y2]; if (y1 != 0) s -= a[x2][y1-1]; if (x1 && y1) s += a[x1-1][y1-1]; return s*s;}void DP() { int i, x1, x2, y1, y2, j; for(i = 0; i < n-1; i++) for(x1 = 0; x1 < 8; x1++) for(y1 = 0; y1 < 8; y1++) for(x2 = x1; x2 < 8; x2++) for(y2 = y1; y2 < 8; y2++) { dp[i+1][x1][y1][x2][y2] = (double)(1<<30);//这个地方其实挺关键的 for(j = x1; j < x2; j++) { dp[i+1][x1][y1][x2][y2] = min(dp[i][x1][y1][j][y2] + dp[0][j+1][y1][x2][y2], dp[i+1][x1][y1][x2][y2]); dp[i+1][x1][y1][x2][y2] = min(dp[i][j+1][y1][x2][y2] + dp[0][x1][y1][j][y2], dp[i+1][x1][y1][x2][y2]); } for(j = y1; j < y2; j++) { dp[i+1][x1][y1][x2][y2] = min(dp[i][x1][y1][x2][j] + dp[0][x1][j+1][x2][y2], dp[i+1][x1][y1][x2][y2]); dp[i+1][x1][y1][x2][y2] = min(dp[i][x1][j+1][x2][y2] + dp[0][x1][y1][x2][j], dp[i+1][x1][y1][x2][y2]); } }}int main() { int i, j, k, t; scanf("%d", &n); for(i = 0; i < 8; i++) { for(j = 0; j < 8; j++) { scanf("%d", &a[i][j] ); if(j != 0) a[i][j] += a[i][j-1]; } for(j = 0; j < 8; j++) a[i][j] += a[i-1][j]; } x = a[7][7]*1.0; for(i = 0; i < 8; i++) for(j = 0; j < 8; j++) for(k = i; k < 8; k++) for(t = j; t < 8; t++) dp[0][i][j][k][t] = sub(i, j, k, t); DP(); x = (x/n)*(x/n); double result; result = sqrt(dp[n-1][0][0][7][7] / n-x); printf("%.3f", result); return 0;}对了,上面的dp数组,没必要用double;
二 记忆搜索
代码:
#include <iostream>#include <cstring>#include <cstdio>#include <cmath>#include <algorithm>const int M = 8;using namespace std;int dp[16][M][M][M][M];int a[M][M], n, v;int sub(int x1, int y1, int x2, int y2) { int s; s =a[x2][y2]; if (x1 != 0) s -= a[x1-1][y2]; if (y1 != 0) s -= a[x2][y1-1]; if (x1 && y1) s += a[x1-1][y1-1]; return s*s;}int DP(int i, int x1, int y1, int x2, int y2) { int j; if(dp[i][x1][y1][x2][y2]!=-1) return dp[i][x1][y1][x2][y2];//记忆的这一部分,算过一遍就不要再算了; dp[i][x1][y1][x2][y2] = 1<<30;//这句话其实隐藏了一个效果,不是你想的辣么简单 for(j = x1; j < x2; j++) { dp[i][x1][y1][x2][y2] = min(dp[i][x1][y1][x2][y2], DP(i-1, x1, y1, j, y2) + dp[0][j+1][y1][x2][y2]); dp[i][x1][y1][x2][y2] = min(dp[i][x1][y1][x2][y2], DP(i-1, j+1, y1, x2, y2) + dp[0][x1][y1][j][y2]); } for(j = y1; j < y2; j++) { dp[i][x1][y1][x2][y2] = min(dp[i][x1][y1][x2][y2], DP(i-1, x1, y1, x2, j) + dp[0][x1][j+1][x2][y2]); dp[i][x1][y1][x2][y2] = min(dp[i][x1][y1][x2][y2], DP(i-1, x1, j+1, x2, y2) + dp[0][x1][y1][x2][j]); } return dp[i][x1][y1][x2][y2];}int main() { int i, j, k, t; double x; scanf("%d", &n); for(i = 0; i < 8; i++) { for(j = 0; j < 8; j++) { scanf("%d", &a[i][j] ); if(j != 0) a[i][j] += a[i][j-1]; } for(j = 0; j < 8; j++) a[i][j] += a[i-1][j]; } memset(dp, -1, sizeof(dp)); x = a[7][7]*1.0; for(i = 0; i < 8; i++) for(j = 0; j < 8; j++) for(k = i; k < 8; k++) for(t = j; t < 8; t++) dp[0][i][j][k][t] = sub(i, j, k, t); double result = DP(n-1, 0, 0, 7, 7); x = (x/n)*(x/n); result = sqrt(result/n - x); printf("%.3f", result); return 0;}
三,再发一个dp+滚动数组的
代码:
#include <iostream>#include <cstring>#include <cstdio>#include <cmath>const short M = 8;using namespace std;int dp[3][M][M][M][M];int a[M][M], n, v;int sub(int x1, int y1, int x2, int y2) { int s; s =a[x2][y2]; if (x1 != 0) s -= a[x1-1][y2]; if (y1 != 0) s -= a[x2][y1-1]; if (x1 && y1) s += a[x1-1][y1-1]; return s*s;}void DP() { int i, x1, x2, y1, y2, j; v = 0; for(i = 1; i < n-1; i++) { for(x1 = 0; x1 < 8; x1++) for(y1 = 0; y1 < 8; y1++) for(x2 = x1; x2 < 8; x2++) for(y2 = y1; y2 < 8; y2++) { dp[v^1][x1][y1][x2][y2] = (1<<30); for(j = x1; j < x2; j++) { dp[v^1][x1][y1][x2][y2] = min(dp[v][x1][y1][j][y2] + dp[2][j+1][y1][x2][y2], dp[v^1][x1][y1][x2][y2]); dp[v^1][x1][y1][x2][y2] = min(dp[v][j+1][y1][x2][y2] + dp[2][x1][y1][j][y2], dp[v^1][x1][y1][x2][y2]); } for(j = y1; j < y2; j++) { dp[v^1][x1][y1][x2][y2] = min(dp[v][x1][y1][x2][j] + dp[2][x1][j+1][x2][y2], dp[v^1][x1][y1][x2][y2]); dp[v^1][x1][y1][x2][y2] = min(dp[v][x1][j+1][x2][y2] + dp[2][x1][y1][x2][j], dp[v^1][x1][y1][x2][y2]); } } v ^= 1; }}int main() { int i, j, k, t, x1, x2, y1, y2; double x; scanf("%d", &n); for(i = 0; i < 8; i++) { for(j = 0; j < 8; j++) { scanf("%d", &a[i][j] ); if(j != 0) a[i][j] += a[i][j-1]; } for(j = 0; j < 8; j++) a[i][j] += a[i-1][j]; } x = a[7][7]*1.0; for(i = 0; i < 8; i++) for(j = 0; j < 8; j++) for(k = i; k < 8; k++) for(t = j; t < 8; t++) dp[2][i][j][k][t] = sub(i, j, k, t); for(x1 = 0; x1 < 8; x1++) for(y1 = 0; y1 < 8; y1++) for(x2 = x1; x2 < 8; x2++) for(y2 = y1; y2 < 8; y2++) { dp[0][x1][y1][x2][y2] = (1<<30); for(j = x1; j < x2; j++) { dp[0][x1][y1][x2][y2] = min(dp[2][x1][y1][j][y2] + dp[2][j+1][y1][x2][y2], dp[0][x1][y1][x2][y2]); dp[0][x1][y1][x2][y2] = min(dp[2][j+1][y1][x2][y2] + dp[2][x1][y1][j][y2], dp[0][x1][y1][x2][y2]); } for(j = y1; j < y2; j++) { dp[0][x1][y1][x2][y2] = min(dp[2][x1][y1][x2][j] + dp[2][x1][j+1][x2][y2], dp[0][x1][y1][x2][y2]); dp[0][x1][y1][x2][y2] = min(dp[2][x1][j+1][x2][y2] + dp[2][x1][y1][x2][j], dp[0][x1][y1][x2][y2]); } } DP(); x = (x/n)*(x/n); double result; result = sqrt((double)(dp[v][0][0][7][7]) / n-x); printf("%.3f", result); return 0;}
我上面总是说 dp[i][x1][y1][x2][y2] = 1<<30; 这句话很重要如果改成下面这样行吗;
if(x1 != x2 || y1 != y2) dp[i+1][x1][y1][x2][y2] = (double)(1<<30);
答案是不行,懒得讲了。
0 0
- poj 1191 棋盘分割 dp-进阶
- poj 1191 棋盘分割 DP
- POJ 1191 棋盘分割 DP
- poj-1191- 棋盘分割dp
- POJ 1191 棋盘分割 DP
- poj - 1191 - 棋盘分割(dp)
- POJ 1191 棋盘分割(DP)
- poj 1191 棋盘分割(dp)
- poj 1191 棋盘分割(DP)
- POJ 1191 棋盘分割 (DP)
- 【POJ 1191】 棋盘分割(DP)
- [poj 1191] 棋盘分割 划分型DP
- poj 1191 棋盘分割(dp,黑书dp例二)
- POJ 1191棋盘分割
- poj 1191 棋盘分割
- Poj 1191 棋盘分割
- poj 1191 棋盘分割
- POJ 1191 棋盘分割
- NandFlash初始化
- 【NOIP2016提高A组模拟8.19】(雅礼联考day2)树上路径
- 数据库增删改查基本语句
- 【NOIP2016提高A组模拟8.19】公约数
- 8天学通MongoDB——第六天 分片技术
- poj 1191 棋盘分割 dp-进阶
- radiogroup .clearCheck()之后 里面的RadioButton要点击2次才能被选中
- QT编程之Layout
- 举例阐述游戏战斗系统设计的基本规则
- Dubbo&ZK分布式服务化改造(四)——Dubbo多注册中心 & 服务迁移
- Web 安全问题
- xml在java中的运用
- 8天学通MongoDB——第七天 运维技术
- Qt学习之路_7(线性布局和网格布局初步探索)