poj 1191 搜索+剪枝

题目描述:

中文题,棋盘分割。


解题思路:

搜索所有划分可能。直接搜索肯定会超时,剪枝的思想来源于:计算方差里的变动项为分子的平方求和,而在划分下一格时,由于前面的格子面积已经固定下来,所以可以提前计算面积和平均面积差的平方和,这样就能够提前停止部分无效的搜索状态。

貌似有动规做的,递推公式里包含了五维数组。懒得看了。


代码:

#include <stdio.h>
#define N 16
#define MAX 100000000

long double sum=0, variance=0, min=MAX, avg_sq;
double chess[8][8];
int n;

double calc_sq(int li, int lj, int ri, int rj){
    double s=0;
    int i, j;
    for(i=li; i<=ri; i++){
        for(j=lj; j<=rj; j++){
            s += chess[i][j];
        }
    }
    return s;
}

void split(int t, int li, int lj, int ri, int rj){
    double sq;
    int i, j;
    
    if(t==n-1){
        sq = calc_sq(li,lj,ri,rj);// calc last square
        variance += (sq-avg_sq)*(sq-avg_sq);
        //variance = sqrt(variance/((double)n))
        if( variance < min){
            min = variance;
        }
        variance -= (sq-avg_sq)*(sq-avg_sq);
    }else{
        for(i=li; i<ri; i++){
            //take bottom as next
            sq = calc_sq(li,lj,i,rj);//calc up square
            variance += (sq-avg_sq)*(sq-avg_sq);
            if(variance < min)
                split(t+1, i+1, lj, ri, rj);
            variance -= (sq-avg_sq)*(sq-avg_sq);
            //take up as next
            if(t!=n-2){
                sq = calc_sq(i+1, lj, ri, rj);//calc bottom square
                variance += (sq-avg_sq)*(sq-avg_sq);
                if(variance < min)
                    split(t+1,li,lj,i,rj);
                variance -= (sq-avg_sq)*(sq-avg_sq);
            }
        }
        for(j=lj; j<rj; j++){
            //take left as next
            sq = calc_sq(li,j+1,ri,rj);
            variance += (sq-avg_sq)*(sq-avg_sq);
            if(variance < min)
                split(t+1,li,lj,ri,j);
            variance -= (sq-avg_sq)*(sq-avg_sq);
            
            //take right as next
            if(t!=n-2){
                sq = calc_sq(li,lj,ri,j);
                variance += (sq-avg_sq)*(sq-avg_sq);
                if(variance < min)
                    split(t+1,li,j+1,ri,rj);
                variance -= (sq-avg_sq)*(sq-avg_sq);
            }
        }
    }
}


main(){
    int i, j;
    scanf("%d",&n);
    for(i=0;i<8;i++)
        for(j=0;j<8;j++){
            scanf("%lf",&chess[i][j]);
            sum += chess[i][j];
        }
    avg_sq = sum/((double)(n));
    split(0,0,0,7,7);
    printf("%.3f\n", sqrt(min/((double)n)));
    
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值