您的位置:首页 > 其它

NYOJ746 整数划分(四)(深搜DFS,区间DP)

2017-07-31 16:23 513 查看
题目;


整数划分(四)

时间限制:1000 ms  |  内存限制:65535 KB
难度:3

描述

       暑假来了,hrdv 又要留学校在参加ACM集训了,集训的生活非常Happy

(ps:你懂得),可是他最近遇到了一个难题,让他百思不得其解,他非常郁闷。。亲爱的你能帮帮他吗?

      问题是我们经常见到的整数划分,给出两个整数 n , m ,要求在 n 中加入m - 1 个乘号,将n分成m段,求出这m段的最大乘积

输入第一行是一个整数T,表示有T组测试数据

接下来T行,每行有两个正整数 n,m ( 1<= n < 10^19, 0 < m <= n的位数);

输出输出每组测试样例结果为一个整数占一行
样例输入
2
111 2
1111 2


样例输出
11
121


来源经典题目

思路:

搜索的思路就不说了,先初始化一下每一个区间的值,然后再相乘就好。

DP的思路是先预处理出每一个区间的值。

然后用dp[i][j]表示把0~i这个区间划分成j段所能获得的最大乘积。

则:

dp[i][j]=max(dp[i][j],dp[k][j-1]*sum[k+1][i])

代码1(dfs):

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <iostream>
#include <stack>
#include <queue>
#include <vector>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define N 100000+10
#define M 10000+20
#define MOD 1000000000+7
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
char s[100];
ll sum[100][100];
ll len,maxx,n,m;
void dfs(ll i,ll ans,ll step)
{
if(step==m)
{
maxx=max(ans,maxx);
return;
}
for(ll j=1; j<=len-m+1; j++)//i和j是区间
if(i+j<=len)
dfs(i+j,ans*sum[i+1][i+j],step+1);
}
int main()
{
ll t;
scanf("%lld",&t);
while(t--)
{
maxx=0;
scanf("%s%lld",s+1,&m);
len=strlen(s+1);
for(ll i=1; i<=len; i++)
{
sum[i][i]=s[i]-'0';
for(ll j=i+1; j<=len; j++)
sum[i][j]=sum[i][j-1]*10+s[j]-'0';
}
dfs(0,1,0);
printf("%lld\n",maxx);
}
return 0;
}


代码2(DP):
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <iostream>
#include <stack>
#include <queue>
#include <vector>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define N 100000+10
#define M 10000+20
#define MOD 1000000000+7
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
char s[100];
ll sum[100][100],dp[100][100];
ll n,m;
int main()
{
ll t;
scanf("%lld",&t);
while(t--)
{
mem(dp,0);
scanf("%s%lld",s,&m);
n=strlen(s);
for(ll i=0; i<n; i++)
{
sum[i][i]=s[i]-'0';
for(ll j=i+1; j<n; j++)
sum[i][j]=sum[i][j-1]*10+s[j]-'0';
}
for(ll i=0; i<n; i++)
{
dp[i][1]=sum[0][i];
for(ll j=2; j<=m; j++) //枚举段数
for(ll k=j-2; k<i; k++)
dp[i][j]=max(dp[i][j],dp[k][j-1]*sum[k+1][i]);
}
printf("%lld\n",dp[n-1][m]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: