• poj 1191 棋盘切割 (压缩dp+记忆化搜索)


    一,题意:

    中文题

    二。分析:

    主要利用压缩dp与记忆化搜索思想

    三,代码:

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    using namespace std;
    const int Big=20000000;
    int Mat[10][10];
    int N;
    int sum[10][10];
    int dp[20][10][10][10][10];
    void unit()
    {//求和用sum[i][j]表示ij到左上角的和
        int total;
        for(int i=1; i<=8; i++)
            for(int j=1; j<=8; j++)
            {
                total=Mat[i][j];
                int x_1,y_1;
                x_1=i-1;
                y_1=j-1;
                if(x_1>0)
                    total+=sum[x_1][j];
                if(y_1>0)
                    total+=sum[i][y_1];
                if(x_1>0&&y_1>0)
                    total-=sum[x_1][y_1];
                sum[i][j]=total;
            }
    }
    
    int account(int x_1,int y_1,int x_2,int y_2)
    {//求(x_1,y_1)到(x_2。y_2)区间和
        int total=sum[x_2][y_2];
        int x_3,y_3;
        x_3=x_1-1;
        y_3=y_1-1;
        if(x_3>0)
            total-=sum[x_3][y_2];
        if(y_3>0)
            total-=sum[x_2][y_3];
        if(x_3>0&&y_3>0)
            total+=sum[x_3][y_3];
        return total*total;
    }
    
    int solve(int k,int x_1,int y_1,int x_2,int y_2)
    {//记忆化dp
        if(dp[k][x_1][y_1][x_2][y_2]!=-1)
            return dp[k][x_1][y_1][x_2][y_2];
        if(k==1)
            return dp[k][x_1][y_1][x_2][y_2]=account(x_1,y_1,x_2,y_2);
        if(k>1)
        {
            int Min=Big;
            for(int i=y_1;i<y_2;i++)
            {//横向分割
                int first=account(x_1,y_1,x_2,i);
                int second=account(x_1,i+1,x_2,y_2);
                first+=solve(k-1,x_1,i+1,x_2,y_2);
                second+=solve(k-1,x_1,y_1,x_2,i);
                if(first>second)
                    first=second;
                if(Min>first)
                    Min=first;
            }
            for(int j=x_1;j<x_2;j++)
            {//纵向分割
                int first=account(x_1,y_1,j,y_2);
                int second=account(j+1,y_1,x_2,y_2);
                first+=solve(k-1,j+1,y_1,x_2,y_2);
                second+=solve(k-1,x_1,y_1,j,y_2);
                if(first>second)
                    first=second;
                if(Min>first)
                    Min=first;
            }
            return dp[k][x_1][y_1][x_2][y_2]=Min;
        }
        return dp[k][x_1][y_1][x_2][y_2]=Big;
    }
    
    int main()
    {
        while(scanf("%d",&N)!=EOF)
        {
            double total=0.0;
            for(int i=1; i<=8; i++)
                for(int j=1; j<=8; j++)
                {
                     scanf("%d",&Mat[i][j]);
                     total+=Mat[i][j];
                }
            unit();
            memset(dp,-1,sizeof(dp));
             total=(total/N)*(total/N);
            double key=solve(N,1,1,8,8);
            key=key/N;
           key=sqrt(key-total);
           printf("%0.3f
    ",key);
        }
        return 0;
    }
    


  • 相关阅读:
    菜农大叔抢楼
    实验室博客
    VS2008加入QT
    9G关于新唐M0的ISP的要点
    内部函数和外部函数
    51串口通信
    一个三位整数反向后输出
    C++重载函数定义和用法
    博客记录
    C语言练习笔记更新
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/7069771.html
Copyright © 2020-2023  润新知