UVA 10003

这两天状态太囧了……看啥啥不会,做啥啥WA……这题就纠结了我好几小时

 

 

题目是经典DP,和矩阵相乘的最小乘法次数那个是一样的

 

f[i,j]=min{f[i,k]+f[k,j]}+j-i (k是i,j之间的木棍切割点)

 

f[0,L]就是答案。由于划分阶段貌似比较困难,于是毫不犹豫的使用记忆化搜索

开始的时候f数组开了1000*1000(由于L最大为1000),然后转移状态的时候从把所有的切割点过一遍,复杂度是O(kn^2),k<50,n<1000,照理讲完全没有问题,自己试了最大的数据也是秒杀。

于是提交,居然TLE— —

囧大了,上网看别人怎么说的。有人发现这题的test case奇多无比,很容易超时。

但是算法没问题,看看能不能优化下细节

于是尝试在状态转移时候的那个for循环上做文章,结果种种尝试均失败了……

 

找到个别人的code来参考下,发现dp的状态数居然是50*50

仔细一想,确实是这么回事……居然一直都没发现

改写之后1秒AC了……一次最多算50*50*50次的dp居然花了近1秒……他到底用了多少数据呃……

 

不过之前用那个1000*1000数组的时候也只用到了50*50的空间,状态并没有变多

超时的可能性大概在每次dp前的初始化上……那个初始化1000*1000数组的时间比dp的还要长……

果然是状态问题…………早点休息吧……

 

 

#include<stdio.h> #include<string.h> #define MAX 0xffffff int f[60][60],L,N,ans,c[60]; void input() { scanf("%d",&N); int t; c[0]=0; c[N+1]=L; for(int i=1;i<=N;i++) { scanf("%d",&c[i]); } } int dp(int i,int j) { if(f[i][j]!=-1) return f[i][j]; else if(i==j-1) return f[i][j]=0; else { f[i][j]=MAX; int t; for(int k=i+1;k<j;k++) { t=dp(i,k)+dp(k,j)+c[j]-c[i]; if(f[i][j]>t) f[i][j]=t; } return f[i][j]; } } void solve() { memset(f,-1,sizeof(f)); ans=dp(0,N+1); } void output() { printf("The minimum cutting is %d./n",ans); } int main() { while(scanf("%d",&L)!=EOF && L!=0) { input(); solve(); output(); } }  

你可能感兴趣的:(UVA 10003)