poj1191

来源:互联网 发布:php 时间戳 精确 编辑:程序博客网 时间:2024/06/06 05:36
http://acm.pku.edu.cn/JudgeOnline/problem?id=1191
运用动态规划状态为int d(int k, int x1, int y1, int x2, int y2),表示左上角为(x1, y1),右下角为(x2, y2)的矩阵被切割成n块时可以达到的最小平方和。
状态转移方程为d(k, x1, y1, x2, y2)=min( min( d[k-1, x1, y1, a ,y2]+s[a+1, y1, x2, y2], d[k-1, a+1, y1, x2, y2]+s[x1, y1, a, y2]), min(d[k-1, x1, y1, x2, b]+s[x1, b+1, x2, y2], d[k-1, x1, b+1, x2, y2]+s[x1, y1, x2, b]))。其中x1<=a<x2, y1<=b<y2。
用一个五维数组s保存计算过的状态。val数组中存放
左上角为(0,0)点与右下角为当前位置的矩形的所有元素的和。
关于WA:在代码第16行没有初始化r,所以一直WA。当把r赋一个较大的值后终于AC了:)

可供参考的链接:http://blog.chinaunix.net/u/26924/showart_653969.html
  1. #include <stdio.h>
  2. #include <math.h>
  3. #define SIZE 8
  4. #define min(a,b) ((a)<(b)) ? (a) : (b)
  5. int k;//分割数量
  6. int val[SIZE+1][SIZE+1];//val中每一个位置存放的是左上角为(0,0)点与右下角为当前位置的矩形的所有元素的和
  7. int s[15][SIZE+1][SIZE+1][SIZE+1][SIZE+1];//存储各个状态的值
  8. int sum(int x1, int y1, int x2, int y2)
  9. {
  10.     int ret;
  11.     ret=val[x2][y2]-val[x2][y1-1]-val[x1-1][y2]+val[x1-1][y1-1];
  12.     return ret*ret;
  13. }
  14. int d(int n, int x1, int y1, int x2, int y2)
  15. {//状态:左上角为(x1, y1),右下角为(x2, y2)的矩阵被切割成n块时可以达到的最小平方和
  16.     int i, j, r=100000000;
  17.     if (s[n][x1][y1][x2][y2]!=-1)
  18.         return s[n][x1][y1][x2][y2];
  19.     else{
  20.         if (n==1 || x1==x2 || y1==y2){
  21.             s[n][x1][y1][x2][y2]=sum(x1,y1,x2,y2);
  22.             return s[n][x1][y1][x2][y2];
  23.         }
  24.         else{
  25.             for (i=x1; i<x2; i++)//竖切
  26.                 r=min(r, min(d(n-1, x1, y1, i, y2)+sum(i+1, y1, x2, y2), d(n-1, i+1, y1, x2, y2)+sum(x1, y1, i, y2)));
  27.             for (j=y1; j<y2; j++)//横切
  28.                 r=min(r, min(d(n-1, x1, y1, x2, j)+sum(x1, j+1, x2, y2), d(n-1, x1, j+1, x2, y2)+sum(x1, y1, x2, j)));
  29.             s[n][x1][y1][x2][y2]=r;
  30.             return r;
  31.         }
  32.     }
  33. }
  34. void ReadFile()//读文件
  35. {
  36.     int i, j;
  37.     //freopen("poj1191.txt","r", stdin);
  38.     scanf("%d", &k);
  39.     for (i=1; i<=SIZE; i++){
  40.         for (j=1; j<=SIZE; j++)
  41.             scanf("%d", &val[i][j]);
  42.     }
  43.     for (i=0; i<=SIZE; i++)
  44.         val[0][i]=val[i][0]=0;
  45.     for (i=1; i<=SIZE; i++){
  46.         for (j=1; j<=SIZE; j++)
  47.             val[i][j]+=val[i-1][j]+val[i][j-1]-val[i-1][j-1];
  48.     }
  49. }
  50. void Initial()//初始化s[][][][][]
  51. {
  52.     int i, j, x, y, k;
  53.     for (k=0; k<15; k++){
  54.         for (i=0; i<=SIZE; i++)
  55.             for(j=0; j<=SIZE; j++)
  56.                 for (x=0; x<=SIZE; x++)
  57.                     for (y=0; y<=SIZE; y++)
  58.                         s[k][i][j][x][y]=-1;
  59.     }
  60. }
  61. void OutPut()
  62. {
  63.     double res;
  64.     res=sqrt((double)d(k, 1, 1, SIZE, SIZE)/k-pow(sqrt(sum(1, 1, SIZE, SIZE))/k, 2.0));
  65.     printf("%.3f/n", res);
  66. }
  67. main(int argc, char *argv[])
  68. {
  69.     Initial();
  70.     ReadFile();
  71.     OutPut();
  72. }