pku 1191 棋盘分割 DP / 记忆化搜索
生活随笔
收集整理的這篇文章主要介紹了
pku 1191 棋盘分割 DP / 记忆化搜索
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
http://poj.org/problem?id=1191?
?題意:中文省略.
思路:黑說p116有講解,
主要的狀態(tài)轉(zhuǎn)移方程為
橫著切:?
dp[k][x1][y1][x2][y2] ?= min(dp[k - 1][x1][y1][mid][y2] + dp[1][mid][y1][x2][y2],dp[k - 1][mid][y1][x2][y2] + dp[1][x1][y1][mid][y2]); ? x1 + 1 <= mid < x2
豎著切:
dp[k][x1][y1][x2][y2] ?= min(dp[k - 1][x1][y1][x2][mid] + dp[1][x1][mid][x2][y2],dp[k - 1][x1][mid][x2][y2] + dp[1][x1][y1][x2][mid]); ?y1 + 1<= ?mid < y2
?
?
View Code?#include?<iostream>#include?<cmath>
#include?<cstdio>
#include?<cstring>
#define?maxn?17
#define?N?8
using?namespace?std;
const?int?inf?=?99999999;
int?dp[maxn][9][9][9][9];
int?map[9][9];
int?getDP(int?k,int?x1,int?y1,int?x2,int?y2)
{
????int?mid;
????int?ans?=?inf;
????for?(mid?=?x1?+?1;?mid?<?x2;?++mid)
????{
????????ans?=?min(ans,dp[k?-?1][x1][y1][mid][y2]?+?dp[1][mid][y1][x2][y2]);
????????ans?=?min(ans,dp[k?-?1][mid][y1][x2][y2]?+?dp[1][x1][y1][mid][y2]);
????}
????for?(mid?=?y1?+?1;?mid?<?y2;?++mid)
????{
????????ans?=?min(ans,dp[k?-?1][x1][y1][x2][mid]?+?dp[1][x1][mid][x2][y2]);
????????ans?=?min(ans,dp[k?-?1][x1][mid][x2][y2]?+?dp[1][x1][y1][x2][mid]);
????}
????return?ans;
}
int?main()
{
????//freopen("d.txt","r",stdin);
????int?n,i,j,k;
????int?x1,y1,x2,y2;
????scanf("%d",&n);
????memset(map,0,sizeof(map));
????int?sum?=?0;
????//map存每個矩形的和
????for?(i?=?1;?i?<=?N;?++i)
????for?(j?=?1;?j?<=?N;?++j)
????{
????????scanf("%d",&map[i][j]);
????????sum?+=?map[i][j];
????????map[i][j]?+=?map[i][j?-?1]?+?map[i?-?1][j]?-?map[i?-?1][j?-?1];
????}
????//出事話dp將所有劃分成一個的求出來
????memset(dp,0,sizeof(dp));
????for?(x1?=?0;?x1?<?N;?++x1)
????for?(y1?=?0;?y1?<?N;?++y1)
????for?(x2?=?x1?+?1;?x2?<=?N;?++x2)
????for?(y2?=?y1?+?1;?y2?<=?N;?++y2)
????{
????????int?tmp?=?map[x2][y2]?-?map[x1][y2]?-?map[x2][y1]?+?map[x1][y1];
????????dp[1][x1][y1][x2][y2]?=?tmp*tmp;
????}
????//枚舉求解
????for?(k?=?2;?k?<=?n;?++k)
????for?(x1?=?0;?x1?<?N;?++x1)
????for?(y1?=?0;?y1?<?N;?++y1)
????for?(x2?=?x1?+?1;?x2?<=?N;?++x2)
????for?(y2?=?y1?+?1;?y2?<=?N;?++y2)
????{
????????dp[k][x1][y1][x2][y2]?=?getDP(k,x1,y1,x2,y2);
????}
????double?ans?=?(1.0*dp[n][0][0][8][8])/n?-?(1.0*sum*sum)/(n*n*1.0);
????printf("%.3lf\n",sqrt(ans));
????return?0;
?
?
記憶化搜索:
這里只要能夠推出狀態(tài)轉(zhuǎn)移方程,其實記憶化搜索就很好寫了。
?
View Code?#include?<iostream>#include?<cmath>
#include?<cstdio>
#include?<cstring>
#define?maxn?17
#define?N?8
using?namespace?std;
const?int?inf?=?99999999;
int?dp[maxn][9][9][9][9];
int?map[9][9];
/*int?getDP(int?k,int?x1,int?y1,int?x2,int?y2)
{
????int?mid;
????int?ans?=?inf;
????for?(mid?=?x1?+?1;?mid?<?x2;?++mid)
????{
????????ans?=?min(ans,dp[k?-?1][x1][y1][mid][y2]?+?dp[1][mid][y1][x2][y2]);
????????ans?=?min(ans,dp[k?-?1][mid][y1][x2][y2]?+?dp[1][x1][y1][mid][y2]);
????}
????for?(mid?=?y1?+?1;?mid?<?y2;?++mid)
????{
????????ans?=?min(ans,dp[k?-?1][x1][y1][x2][mid]?+?dp[1][x1][mid][x2][y2]);
????????ans?=?min(ans,dp[k?-?1][x1][mid][x2][y2]?+?dp[1][x1][y1][x2][mid]);
????}
????return?ans;
}*/
int?getS(int?x1,int?y1,int?x2,int?y2)
{
????return?map[x2][y2]?-?map[x1][y2]?-?map[x2][y1]?+?map[x1][y1];
}
int?DP(int?k,int?x1,int?y1,int?x2,int?y2)
{
????int?mid;
????if?(dp[k][x1][y1][x2][y2]?!=?0)?return?dp[k][x1][y1][x2][y2];//記憶的由來
????if?(k?==?1)//分割到最小取得值
????{
????????int?tp?=?getS(x1,y1,x2,y2);
????????dp[1][x1][y1][x2][y2]?=?tp*tp;
????????return?tp*tp;
????}
????int?ans?=?inf;
????//橫向切割
????for?(mid?=?x1?+?1;?mid?<?x2;?++mid)
????{
????????ans?=?min(ans,DP(k?-?1,x1,y1,mid,y2)?+?DP(1,mid,y1,x2,y2));
????????ans?=?min(ans,DP(k?-?1,mid,y1,x2,y2)?+?DP(1,x1,y1,mid,y2));
????}
????//縱向切割
????for?(mid?=?y1?+?1;?mid?<?y2;?++mid)
????{
????????ans?=?min(ans,DP(k?-?1,x1,y1,x2,mid)?+?DP(1,x1,mid,x2,y2));
????????ans?=?min(ans,DP(k?-?1,x1,mid,x2,y2)?+?DP(1,x1,y1,x2,mid));
????}
????dp[k][x1][y1][x2][y2]?=?ans;
????return?ans;
}
int?main()
{
????//freopen("d.txt","r",stdin);
????int?n,i,j;
????scanf("%d",&n);
????memset(map,0,sizeof(map));
????int?sum?=?0;
????//map存每個矩形的和
????for?(i?=?1;?i?<=?N;?++i)
????for?(j?=?1;?j?<=?N;?++j)
????{
????????scanf("%d",&map[i][j]);
????????sum?+=?map[i][j];
????????map[i][j]?+=?map[i][j?-?1]?+?map[i?-?1][j]?-?map[i?-?1][j?-?1];
????}
????memset(dp,0,sizeof(dp));
????int?tmp?=?DP(n,0,0,8,8);
????double?ans?=?(1.0*tmp)/n?-?(sum*sum*1.0)/(n*n*1.0);
????printf("%.3lf\n",sqrt(ans));
????return?0;
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/E-star/archive/2012/08/12/2634248.html
總結(jié)
以上是生活随笔為你收集整理的pku 1191 棋盘分割 DP / 记忆化搜索的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: poj 2948 Martian M
- 下一篇: hdu_2063,二分图最大匹配的学习