您的位置:首页 > 其它

UVA 10970 Big Chocolate(暴力,找规律)

2014-02-20 00:24 363 查看
给你一块n*m的巧克力,现在要把它切成n*m个小块,每刀只能沿着一条直线把一块巧克力切成两部分,问你最少切几刀?

先想想暴力的方法,我们可以用dp[i][j]表示把一块i*j的巧克力切开最少需要几刀,注意到dp[i][j]=dp[j][i],所以我们只需要处理i<=j的情况。显然边界条件是dp[1][j]=j-1。在转移的时候只需要枚举在哪里切开就可以了:

dp[i][j]=min(dp[x][j]+dp[y][j])+1其中x+y=i。

dp[i][j]=min(dp[i][x]+dp[i][y])+1其中x+y=j。

记忆化搜索先预处理出所有情况即可。

有了暴力程序,我们也可以找找规律,我们先固定一个变量,如看看(4,1),(4,2),(4,3),(4,4)有什么规律,很容易发现数列dp[i][j]=dp[i][j-1]+i,又有初始条件dp[i][1]=i-1。得:

dp[i][j]=i*j-1,此式具有对称性(dp[i][j]=dp[j][i]),与事实相合。

暴力代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 309
using namespace std;
int dp[maxn][maxn];
bool vis[maxn][maxn];
int DP(int n,int m)
{
if(vis
[m])return dp
[m];
vis
[m]=1;
int &ans=dp
[m];
if(n==1)return ans=m-1;
if(m==1)return ans=n-1;
ans=(1<<30);
for(int i=1;i<=n-1;i++)
ans=min(ans,DP(min(i,m),max(i,m))+DP(min(n-i,m),max(n-i,m))+1);
for(int i=1;i<=m-1;i++)
ans=min(ans,DP(min(n,i),max(n,i))+DP(min(n,m-i),max(n,m-i))+1);
return ans;
}
int main()
{
int n,m;
for(int i=1;i<=300;i++)
for(int j=i;j<=300;j++)
DP(i,j);
while(scanf("%d%d",&n,&m)!=EOF)
{
printf("%d\n",DP(min(n,m),max(n,m)));
}
}


找规律:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 309
using namespace std;
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
printf("%d\n",n*m-1);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: