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

题目;

整数划分(四)

时间限制: 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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#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


你可能感兴趣的:(【搜索(DFS/BFS)】,【区间dp/状压dp】)