poj1191 [NOI1999] 棋盘分割(dp)
2017-07-30 11:53
537 查看
黑书1.5.1例题2.矩阵越分越小,显然是可以递归处理的。所以我们就想到了dp。求σ=∑i=1n(xi−x¯)2n−−−−−−−−√ 可以化简为 σ2=1n∑i=1nx2i−(x¯)2.平均数是不变的,所以我们只需dp求分成n个矩阵和的平方的和最小值。dp[k][x1][y1][x2][y2]表示把矩阵(x1,y1,x2,y2)(左上角坐标x1,y1,右下角坐标x2,y2)切k刀,能获得的最小值。dp[0]见注释。转移方程为dp[k][x1][y1][x2][y2] = min{
dp[0][x1][y1][t][y2]+dp[k-1][t+1][y1][x2][y2], (x1 <= t < x2)
dp[k-1][x1][y1][t][y2]+dp[0][t+1][y1][x2][y2], (x1 <= t < x2)
dp[0][x1][y1][x2][t]+dp[k-1][x1][t+1][x2][y2], (y1 <= t < y2)
dp[k-1][x1][y1][x2][t]+dp[0][x1][t+1][x2][y2],(y1 <= t < y2)
} 设棋盘边长为m,那么状态数目为m4n,决策数目为O(m),预处理sum数组为O(m2),状态转移时间是O(1)的,所以总的时间复杂度是O(m5n),而m=8,n<16.足够了。
dp[0][x1][y1][t][y2]+dp[k-1][t+1][y1][x2][y2], (x1 <= t < x2)
dp[k-1][x1][y1][t][y2]+dp[0][t+1][y1][x2][y2], (x1 <= t < x2)
dp[0][x1][y1][x2][t]+dp[k-1][x1][t+1][x2][y2], (y1 <= t < y2)
dp[k-1][x1][y1][x2][t]+dp[0][x1][t+1][x2][y2],(y1 <= t < y2)
} 设棋盘边长为m,那么状态数目为m4n,决策数目为O(m),预处理sum数组为O(m2),状态转移时间是O(1)的,所以总的时间复杂度是O(m5n),而m=8,n<16.足够了。
#include <cstdio> #include <cmath> #include <cstring> #define inf 0x7fffffff int map[9][9],n,sum[9][9],tot=0; double dp[16][9][9][9][9]; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } template <typename T> inline T min(T x,T y){return x<y?x:y;} inline double calc(int x1,int y1,int x2,int y2){ double ans=sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1]; return ans*ans; } int main(){ // freopen("a.in","r",stdin); n=read(); for(int i=1;i<=8;++i) for(int j=1;j<=8;++j) map[i][j]=read(); for(int i=1;i<=8;++i) for(int j=1;j<=8;++j){ //sum[i][j]---sum of matrix(1,1,i,j) sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+map[i][j]; tot+=map[i][j]; } for(int x1=1;x1<=8;++x1) for(int y1=1;y1<=8;++y1) for(int x2=x1;x2<=8;++x2) for(int y2=y1;y2<=8;++y2) dp[0][x1][y1][x2][y2]=calc(x1,y1,x2,y2);//dp[0]--marix(x1,y1,x2,y2)的和的平方 for(int k=1;k<n;++k)//切成n块,n-1刀。 for(int x1=1;x1<=8;++x1) for(int y1=1;y1<=8;++y1) for(int x2=x1;x2<=8;++x2) for(int y2=y1;y2<=8;++y2){ dp[k][x1][y1][x2][y2]=inf; for(int t=x1;t<x2;++t){//竖着切。 dp[k][x1][y1][x2][y2]=min(dp[k][x1][y1][x2][y2],dp[k-1][x1][y1][t][y2]+dp[0][t+1][y1][x2][y2]); dp[k][x1][y1][x2][y2]=min(dp[k][x1][y1][x2][y2],dp[0][x1][y1][t][y2]+dp[k-1][t+1][y1][x2][y2]); } for(int t=y1;t<y2;++t){//横着切 dp[k][x1][y1][x2][y2]=min(dp[k][x1][y1][x2][y2],dp[k-1][x1][y1][x2][t]+dp[0][x1][t+1][x2][y2]); dp[k][x1][y1][x2][y2]=min(dp[k][x1][y1][x2][y2],dp[0][x1][y1][x2][t]+dp[k-1][x1][t+1][x2][y2]); } } double ans=dp[n-1][1][1][8][8]/n-(tot*1.0/n)*(tot*1.0/n); printf("%.3f\n",sqrt(ans)); return 0; }
相关文章推荐
- 洛谷 P1436 POJ 1191 [NOI1999 D1T2] 棋盘分割
- poj 1191 棋盘分割 dp-进阶
- poj - 1191 - 棋盘分割(dp)
- poj 1191 棋盘分割 (dp)
- poj-1191- 棋盘分割dp
- 经典问题六.【二维的区间dp】棋盘分割 poj 1191
- poj&nbsp;1191&nbsp;棋盘分割&nbsp;dp
- poj-1191- 棋盘分割dp
- POJ 1191 && HDU 2517 棋盘分割(dp)
- POJ 1191 棋盘分割(DP)
- poj 1191 棋盘分割(dp)
- POJ 1191 棋盘分割(DP)
- [poj1191] [NOI1999] 棋盘分割 DP
- [poj 1191] 棋盘分割 划分型DP
- POJ 1191 棋盘分割 DP
- 【DP】 POJ 1191 棋盘分割 记忆化搜索
- poj 1191 棋盘分割(DP)
- poj1191-dp棋盘分割
- POJ 1191 棋盘分割【区间类DP】
- 【DP】 POJ 1191 棋盘分割 记忆化搜索