小白算法练习 dp练习001-区间dp NYOJ 石子合并,整数划分 POJ Brackets

石子合并(一)

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 3
描述
    有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。
输入
有多组测试数据,输入到文件结束。
每组测试数据第一行有一个整数n,表示有n堆石子。
接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开
输出
输出总代价的最小值,占单独的一行
样例输入
3
1 2 3
7
13 7 8 16 21 4 18

样例输出

9
239

代码

#include<iostream>
#include<fstream>
#include<cstring>
#include<algorithm>
#include<stdio.h>
using namespace std;
const int Max=205;
const int INF=1000008;
int main(){
	int n;
	while(cin>>n && n!=EOF)
	{
		int a[Max]={0};
		int sum[Max]={0};
		for(int i=1;i<=n;i++)
					cin>>a[i];
			sum[i]=sum[i-1]+a[i];
		}
		int dp[Max][Max]={0};
		int Min=10000;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				dp[j][j+i]=INF;
				if(i+j>n) break;
				for(int k=j;k<=j+i;k++)
				{
					dp[j][j+i]=min( (dp[j][k]+dp[k+1][j+i]),dp[j][j+i]);
				}
				dp[j][j+i]+=sum[j+i]-sum[j-1];
			}
		}
		cout<<dp[1][n]<<endl;
	}	
	return 0;
} 

Brackets
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 8962 Accepted: 4809

Description

We give the following inductive definition of a “regular brackets” sequence:

  • the empty sequence is a regular brackets sequence,
  • if s is a regular brackets sequence, then (s) and [s] are regular brackets sequences, and
  • if a and b are regular brackets sequences, then ab is a regular brackets sequence.
  • no other sequence is a regular brackets sequence

For instance, all of the following character sequences are regular brackets sequences:

(), [], (()), ()[], ()[()]

while the following character sequences are not:

(, ], )(, ([)], ([(]

Given a brackets sequence of characters a1a2 … an, your goal is to find the length of the longest regular brackets sequence that is a subsequence of s. That is, you wish to find the largest m such that for indices i1i2, …, im where 1 ≤ i1 < i2 < … < im ≤ nai1ai2 … aim is a regular brackets sequence.

Given the initial sequence ([([]])], the longest regular brackets subsequence is [([])].

Input

The input test file will contain multiple test cases. Each input test case consists of a single line containing only the characters ()[, and ]; each input test will have length between 1 and 100, inclusive. The end-of-file is marked by a line containing the word “end” and should not be processed.

Output

For each input case, the program should print the length of the longest possible regular brackets subsequence on a single line.

Sample Input

((()))
()()()
([]])
)[)(
([][][)
end

Sample Output

6
6
4
0
6
code
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int Max=108;
const int INF=-1;
int dp[Max][Max]={0};
int main(){
	char str[Max]="";
	while(cin>>str && strcmp(str,"end")!=0)
	{
 		memset(dp,0,sizeof(dp));
		int len=strlen(str);
 		for(int i=1;i<len;i++)
 		{
 			for(int j=0;j<len;j++)
			{
				if( (j+i)>len ) continue;
				dp[j][j+i]=INF;
				if( ( str[j]=='(' && str[i+j]==')' ) || ( str[j]=='[' && str[i+j]==']' ) )
				{
					dp[j][i+j]=dp[j+1][i+j-1]+2;
				}
				for(int k=j;k<=j+i;k++)
				{
					dp[j][i+j]=max(dp[j][i+j],dp[j][k]+dp[k+1][i+j]);	
				} 	
			}	
		}
		cout<<dp[0][len-1]<<endl;
	}
	return 0;
} 
区间dp在我的理解就是 数组储存的状态就是存放的是一个区间的最优值,他的目的就是从内往外扩,或者从外往内缩,注意的地方
是区间dp的最重要的状态的转移 实质上是由于区间大小变化而造成的 ,也就是第一层循环是区间的大小,可以尝试这样去理解区间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
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
using namespace std;
char str[20]="";
long long hf[50][50]={0};
long long dp[50][50]={0};
long long m;
int main(){
	
	freopen("../io/整数划分.in","r",stdin);
	
	int T;
	cin>>T;
	while(T--)
	{
		memset(hf,0,sizeof(hf));
		memset(dp,0,sizeof(dp));
		m=0;
			
		scanf("%s%d",str,&m); 
		
		for(int i=0;i<strlen(str);i++)
		{
			hf[i][i]=str[i]-'0';
			for(int j=i;j<strlen(str);j++)
			{
				hf[i][j]=hf[i][j-1]*10+(str[j]-'0');
			}
			dp[i][0]=hf[0][i];
		}   //hf存放从i到j的数字大小
		
		for(int i=1;i<strlen(str);i++)
		{
			for(int k=1;k<=i;k++)
			{
				for(int l=0;l<i;l++)
				{
					dp[i][k]=max(dp[i][k],dp[l][k-1]*hf[l+1][i]);
				}
			}
		}    //dp存放从开始到i的数分成k次最大值
		
		cout<<dp[strlen(str)-1][m-1]<<endl;
	}
	return 0;	
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值