poj-1191的题目是什么?能否详细介绍一下这个算法题目的解题思路?

2026-04-12 01:531阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1339个文字,预计阅读时间需要6分钟。

poj-1191的题目是什么?能否详细介绍一下这个算法题目的解题思路?

pythondef rewrite_fake_innovation_header(content): simplified_content=content.replace(原创, 改写).replace(以下, 此处).replace(内容, 信息) return simplified_content[:100]

poj-1191的题目是什么?能否详细介绍一下这个算法题目的解题思路?

示例original_content=/**/592K32MSC++result=rewrite_fake_innovation_header(original_content)print(result)


//592K 32MS C++ #include <cstdio> #include <cstring> #include <cmath> using namespace std; long DP[16][9][9][9][9]; int chess[8][8]; long getSquareSum(int x1, int y1, int x2, int y2) { if (x1 > x2 || y1 < y2) { return 0; } long sum = 0; for (int i = y2; i <= y1; i++) { for (int j = x1; j <= x2; j++) { sum += chess[j][i]; } } return sum*sum; } int N; #define INF 99999999 inline long min(long a, long b) { return a < b ? a: b; } long totalSum; void getMin() { memset(DP, 0, sizeof(DP)); for (int k = 1; k <= N; k++) { for (int x1 = 0; x1 <= 7; x1++) { for (int y1 = 0; y1 <= 7; y1++) { for (int x2 = 0; x2 <= 7; x2++) { for (int y2 = 0; y2 <= 7; y2++) { if (k == 1) { DP[k][x1][y1][x2][y2] = getSquareSum(x1, y1, x2, y2); } else if (x2 == x1 && y1 == y2) {// impossible to cut to k parts // printf("%d %d %d %d %d\n", k, x1, y1, x2, y2); DP[k][x1][y1][x2][y2] = INF; // } else if (x2 - x1 + 1 >= k && y1 - y2 + 1 < k) { // only can cut x // DP[k][x1][y1][x2][y2] = INF; // for (int cutPos = x1; cutPos <= x2; cutPos++) { // long chose1 = getSquareSum(x1,y1, cutPos, y2) + DP[k-1][cutPos+1][y1][x2][y2]; // long chose2 = getSquareSum(cutPos+1, y1, x2, y2) + DP[k-1][x1][y1][cutPos][y2]; // long tmp = min(chose1, chose2); // DP[k][x1][y1][x2][y2] = min(tmp, DP[k][x1][y1][x2][y2]); // } // } else if (x2 - x1 < k && y1 - y2 >= k) { // only can cut y // DP[k][x1][y1][x2][y2] = INF; // for (int cutPos = y2; cutPos <= y1; cutPos++) { // long chose1 = getSquareSum(x1, y1, x2, cutPos) + DP[k-1][x1][cutPos-1][x2][y2]; // long chose2 = getSquareSum(x1, cutPos-1, x2, y2) + DP[k-1][x1][y1][x2][cutPos]; // long tmp = min(chose1, chose2); // DP[k][x1][y1][x2][y2] = min(tmp, DP[k][x1][y1][x2][y2]); // } } else { DP[k][x1][y1][x2][y2] = INF; for (int cutPos = x1; cutPos <= x2; cutPos++) { long chose1 = getSquareSum(x1,y1, cutPos, y2) + DP[k-1][cutPos+1][y1][x2][y2]; long chose2 = getSquareSum(cutPos+1, y1, x2, y2) + DP[k-1][x1][y1][cutPos][y2]; long tmp = min(chose1, chose2); DP[k][x1][y1][x2][y2] = min(tmp, DP[k][x1][y1][x2][y2]); } for (int cutPos = y2; cutPos <= y1; cutPos++) { long chose1 = getSquareSum(x1, y1, x2, cutPos) + DP[k-1][x1][cutPos-1][x2][y2]; long chose2 = getSquareSum(x1, cutPos-1, x2, y2) + DP[k-1][x1][y1][x2][cutPos]; long tmp = min(chose1, chose2); DP[k][x1][y1][x2][y2] = min(tmp, DP[k][x1][y1][x2][y2]); } } } } } } } // printf("%ld %ld\n", DP[N][0][7][7][0], DP[1][0][7][7][0]); // printf("%ld\n", DP[N][0][7][7][0]); double ans=sqrt(DP[N][0][7][7][0]*1.0/N-((totalSum*1.0)/N*(totalSum*1.0)/N)); printf("%.3f\n", ans); } int main() { scanf("%d", &N); totalSum = 0; for (int i = 0; i <= 7; i++) { for (int j = 0; j <= 7; j++) { scanf("%d", &chess[j][i]); // printf("%d\n", chess[j][i]); totalSum += chess[j][i]; } } getMin(); }

转化稍微有些难度,主要是要将方程变下形,然后才能看出来:

S^2 = 1/n *(∑(Xi - X)^2)

= 1/n(n*X^2 + ∑Xi^2 - 2*X∑Xi)

= 1/n(∑Xi^2) - X^2

这里的Xi是每个切割出来的矩形的矩形和,X是整个大矩形的矩形和/(8*8) , X 在输入完数据以后就确定了, 那么 为了使S尽量小,就要尽量使Xi(1~N)的平方和 的和 尽量小了,

一个重要的理解是,题目最后要得到N个矩形, 那么一共要切 N - 1刀, 注意的是,一个矩形被从大矩形切出来以后,就不能再被切割了,而是作为最后的N个矩形中的一块存在,这一点很重要,否则,如果之前切出来的矩阵也可以被切,就得不到下面的状态方程了:

DP[K][x1][y1][x2][y2]:

指的是对于 左上角是(x1, y1), 右下角是(x2, y2)的矩阵部分进行切割,得到K块 子矩阵时, K个矩阵的矩阵和的平方的和的最小值,

那么显然,题目要求其实就是 DP[N][0][8][8][0]这个值,

递归如下:

<case 1>: 如果K== 1, 那么不需要再切割,只有一个矩阵, 直接返回(x1, y1, x2, y2)所代表的矩阵和的平方即可。

<case 2>: 如果 K >1, 但是此时 x1 == x2, y1 = y2, 即只剩下一个单位块了,不可能再分割,这种无效情况,设为INF(无穷大,因为本题要的是极小值,所以INF代表无效情况)

自己刚开始2B了,code注释掉的那一段就是没想清楚,把有些有效情况也给无效化了.

<case 3>: 如果可以分割, 那么就从当前的矩阵割下一块,这一刀一共有 (x2 - x1 + y1 - y2 )种割法, 分别对应矩阵内部的每一条与x轴平行或与y轴平行的线,而在切完以后,

当前矩阵变成了两部分,A和B,而这时候还有两种选择: 继续切割A 或者 继续切割B, DP在此时的取值就是这么多分支情况中,那个矩阵和的平方的和最小的值。

dp[k,x1,y1,x2,y2] =min{ min{dp[k-1,x1,y1,a,y2]+S[a+1,y1,x2,y2] , dp[k-1,a+1,y1,x2,y2]+S[x1,y1,a,y2]}(x1<=a<x2), min{dp[k-1,x1,y1,x2,b]+S[x1,b+1,x2,y2] , dp[k-1,x1,b+1,x2,y2]+S[x1,y1,x2,b]}(y1<=b<y2) }

最后DP的5重循环完了以后,就可以带入公式计算最终值了, .3f输出.

一开始还准备将矩阵先预处理一下,得到从(0,0)到各个点的矩阵和, 这样在后方要得到(x1, y1) 到 (x2, y2)的矩阵和的时候会快点,但是看到矩阵只有8*8, 因此直接野蛮了一把,也过了.

本文共计1339个文字,预计阅读时间需要6分钟。

poj-1191的题目是什么?能否详细介绍一下这个算法题目的解题思路?

pythondef rewrite_fake_innovation_header(content): simplified_content=content.replace(原创, 改写).replace(以下, 此处).replace(内容, 信息) return simplified_content[:100]

poj-1191的题目是什么?能否详细介绍一下这个算法题目的解题思路?

示例original_content=/**/592K32MSC++result=rewrite_fake_innovation_header(original_content)print(result)


//592K 32MS C++ #include <cstdio> #include <cstring> #include <cmath> using namespace std; long DP[16][9][9][9][9]; int chess[8][8]; long getSquareSum(int x1, int y1, int x2, int y2) { if (x1 > x2 || y1 < y2) { return 0; } long sum = 0; for (int i = y2; i <= y1; i++) { for (int j = x1; j <= x2; j++) { sum += chess[j][i]; } } return sum*sum; } int N; #define INF 99999999 inline long min(long a, long b) { return a < b ? a: b; } long totalSum; void getMin() { memset(DP, 0, sizeof(DP)); for (int k = 1; k <= N; k++) { for (int x1 = 0; x1 <= 7; x1++) { for (int y1 = 0; y1 <= 7; y1++) { for (int x2 = 0; x2 <= 7; x2++) { for (int y2 = 0; y2 <= 7; y2++) { if (k == 1) { DP[k][x1][y1][x2][y2] = getSquareSum(x1, y1, x2, y2); } else if (x2 == x1 && y1 == y2) {// impossible to cut to k parts // printf("%d %d %d %d %d\n", k, x1, y1, x2, y2); DP[k][x1][y1][x2][y2] = INF; // } else if (x2 - x1 + 1 >= k && y1 - y2 + 1 < k) { // only can cut x // DP[k][x1][y1][x2][y2] = INF; // for (int cutPos = x1; cutPos <= x2; cutPos++) { // long chose1 = getSquareSum(x1,y1, cutPos, y2) + DP[k-1][cutPos+1][y1][x2][y2]; // long chose2 = getSquareSum(cutPos+1, y1, x2, y2) + DP[k-1][x1][y1][cutPos][y2]; // long tmp = min(chose1, chose2); // DP[k][x1][y1][x2][y2] = min(tmp, DP[k][x1][y1][x2][y2]); // } // } else if (x2 - x1 < k && y1 - y2 >= k) { // only can cut y // DP[k][x1][y1][x2][y2] = INF; // for (int cutPos = y2; cutPos <= y1; cutPos++) { // long chose1 = getSquareSum(x1, y1, x2, cutPos) + DP[k-1][x1][cutPos-1][x2][y2]; // long chose2 = getSquareSum(x1, cutPos-1, x2, y2) + DP[k-1][x1][y1][x2][cutPos]; // long tmp = min(chose1, chose2); // DP[k][x1][y1][x2][y2] = min(tmp, DP[k][x1][y1][x2][y2]); // } } else { DP[k][x1][y1][x2][y2] = INF; for (int cutPos = x1; cutPos <= x2; cutPos++) { long chose1 = getSquareSum(x1,y1, cutPos, y2) + DP[k-1][cutPos+1][y1][x2][y2]; long chose2 = getSquareSum(cutPos+1, y1, x2, y2) + DP[k-1][x1][y1][cutPos][y2]; long tmp = min(chose1, chose2); DP[k][x1][y1][x2][y2] = min(tmp, DP[k][x1][y1][x2][y2]); } for (int cutPos = y2; cutPos <= y1; cutPos++) { long chose1 = getSquareSum(x1, y1, x2, cutPos) + DP[k-1][x1][cutPos-1][x2][y2]; long chose2 = getSquareSum(x1, cutPos-1, x2, y2) + DP[k-1][x1][y1][x2][cutPos]; long tmp = min(chose1, chose2); DP[k][x1][y1][x2][y2] = min(tmp, DP[k][x1][y1][x2][y2]); } } } } } } } // printf("%ld %ld\n", DP[N][0][7][7][0], DP[1][0][7][7][0]); // printf("%ld\n", DP[N][0][7][7][0]); double ans=sqrt(DP[N][0][7][7][0]*1.0/N-((totalSum*1.0)/N*(totalSum*1.0)/N)); printf("%.3f\n", ans); } int main() { scanf("%d", &N); totalSum = 0; for (int i = 0; i <= 7; i++) { for (int j = 0; j <= 7; j++) { scanf("%d", &chess[j][i]); // printf("%d\n", chess[j][i]); totalSum += chess[j][i]; } } getMin(); }

转化稍微有些难度,主要是要将方程变下形,然后才能看出来:

S^2 = 1/n *(∑(Xi - X)^2)

= 1/n(n*X^2 + ∑Xi^2 - 2*X∑Xi)

= 1/n(∑Xi^2) - X^2

这里的Xi是每个切割出来的矩形的矩形和,X是整个大矩形的矩形和/(8*8) , X 在输入完数据以后就确定了, 那么 为了使S尽量小,就要尽量使Xi(1~N)的平方和 的和 尽量小了,

一个重要的理解是,题目最后要得到N个矩形, 那么一共要切 N - 1刀, 注意的是,一个矩形被从大矩形切出来以后,就不能再被切割了,而是作为最后的N个矩形中的一块存在,这一点很重要,否则,如果之前切出来的矩阵也可以被切,就得不到下面的状态方程了:

DP[K][x1][y1][x2][y2]:

指的是对于 左上角是(x1, y1), 右下角是(x2, y2)的矩阵部分进行切割,得到K块 子矩阵时, K个矩阵的矩阵和的平方的和的最小值,

那么显然,题目要求其实就是 DP[N][0][8][8][0]这个值,

递归如下:

<case 1>: 如果K== 1, 那么不需要再切割,只有一个矩阵, 直接返回(x1, y1, x2, y2)所代表的矩阵和的平方即可。

<case 2>: 如果 K >1, 但是此时 x1 == x2, y1 = y2, 即只剩下一个单位块了,不可能再分割,这种无效情况,设为INF(无穷大,因为本题要的是极小值,所以INF代表无效情况)

自己刚开始2B了,code注释掉的那一段就是没想清楚,把有些有效情况也给无效化了.

<case 3>: 如果可以分割, 那么就从当前的矩阵割下一块,这一刀一共有 (x2 - x1 + y1 - y2 )种割法, 分别对应矩阵内部的每一条与x轴平行或与y轴平行的线,而在切完以后,

当前矩阵变成了两部分,A和B,而这时候还有两种选择: 继续切割A 或者 继续切割B, DP在此时的取值就是这么多分支情况中,那个矩阵和的平方的和最小的值。

dp[k,x1,y1,x2,y2] =min{ min{dp[k-1,x1,y1,a,y2]+S[a+1,y1,x2,y2] , dp[k-1,a+1,y1,x2,y2]+S[x1,y1,a,y2]}(x1<=a<x2), min{dp[k-1,x1,y1,x2,b]+S[x1,b+1,x2,y2] , dp[k-1,x1,b+1,x2,y2]+S[x1,y1,x2,b]}(y1<=b<y2) }

最后DP的5重循环完了以后,就可以带入公式计算最终值了, .3f输出.

一开始还准备将矩阵先预处理一下,得到从(0,0)到各个点的矩阵和, 这样在后方要得到(x1, y1) 到 (x2, y2)的矩阵和的时候会快点,但是看到矩阵只有8*8, 因此直接野蛮了一把,也过了.