uva10003+uva765+uva111

三种基础dp

uva10003:

记忆化搜索

递推公式:dp[u][v] = min(dp[u][k]+dp[k][v]+a[v]-a[u], dp[u][v])

意思就是在某两个断点之间(0和m+1也算)选择断那个断点或不断,那么耗费自然是当前的全长

代码:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 1005;
int n ,m;
int dp[maxn][maxn];
int a[55];
int Dp(int u, int v) {
	if(dp[u][v] >= 0) return dp[u][v];
	dp[u][v] = Dp(u, u+1) + Dp(u+1, v) + a[v]-a[u];
	for(int i=u+2; i<v; i++) {
		int temp = Dp(u, i) + Dp(i, v) + a[v]-a[u];
		dp[u][v] = min(dp[u][v], temp);
	}
	return dp[u][v];
		
}
int main() {
	while(scanf("%d", &n) != EOF && n) {
		scanf("%d", &m);
		for(int i=1; i<=m; i++) {
			scanf("%d", &a[i]);
		}
		for(int i=0; i<m+1; i++)
			for(int j=0; j<=m+1; j++) {
				if(j-i == 1 || i-j==1)
					dp[i][j] = 0;
				else dp[i][j] = -1;
			}
		a[0] = 0;
		a[m+1] =  n;
		printf("The minimum cutting is %d.\n", Dp(0, m + 1));  
	}
	return 0;
}

uva675:完全背包

题意:给出五种硬币的面值以及兑换的钱数,那么问有几种组合方式

思路:

完全背包

贴一下Tanky Woo的程序人生的总结:

动态规划算法可分解成从先到后的4个步骤:

1. 描述一个最优解的结构;

2. 递归地定义最优解的值;

3. 以“自底向上”的方式计算最优解的值;

4. 从已计算的信息中构建出最优解的路径。

其中步骤1~3是动态规划求解问题的基础。如果题目只要求最优解的值,则步骤4可以省略。

背包的基本模型就是给你一个容量为V的背包

在一定的限制条件下放进最多(最少?)价值的东西

01背包(ZeroOnePack): 有N件物品和一个容量为V的背包。(每种物品均只有一件)第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。

1for i=1..N
2   for v=V..0
3        f[v]=max{f[v],f[v-c[i]]+w[i]};

完全背包(CompletePack): 有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

for i=1..N
    
for v=0..V
        f[v]
=max{f[v],f[v-c[i]]+w[i]}
在次我们先来回忆下,01背包逆序的原因?是为了是max中的两项是前一状态值,这就对了。
那么这里,我们顺序写,这里的max中的两项当然就是当前状态的值了,为何?
因为每种背包都是无限的。当我们把i从1到N循环时,f[v]表示容量为v在前i种背包时所得的价值,这里我们要添加的不是前一个背包,而是当前背包。所以我们要考虑的当然是当前状态。

多重背包(MultiplePack): 有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

for(int i=0; i<nKind; ++i)
            for(int j=0; j<bag[i]; ++j)//多循环了一层数量
                for(int k=nValue; k>=value[i]; --k)
                    if(nMultiplePack[k] < nMultiplePack[k-value[i]]+weight[i])
                        nMultiplePack[k] = nMultiplePack[k-value[i]] + weight[i];




转载链接:http://www.wutianqi.com/?p=539

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 7500;
int n;
int t[] = {1, 5, 10, 25, 50};
int dp[maxn];
void Dp() {
	dp[0] = 1;
		for(int j=0; j<5; j++) {
			for(int i=t[j]; i<=maxn; i++) {
				dp[i] += dp[i-t[j]];
			}
		}
}

int main() {
	Dp();
	while(scanf("%d", &n)!=EOF) {
		printf("%d\n", dp[n]);
	}
	return 0;
}
uva111

最长公共子序列

代码:


#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n;
const int maxn = 25;
int first[maxn], second[maxn];
int d[maxn][maxn];
void dp() {
	memset(d, 0, sizeof(d));
	for(int i=1; i<=n; i++) {
		for(int j=1; j<=n; j++) {
			if(first[i] == second[j]) {
				d[i][j] = d[i-1][j-1] + 1;

			}
			else  {
				d[i][j] = max(d[i-1][j], d[i][j-1]);
			}
		}
	}
	printf("%d\n", d[n][n]);
}

int main() {
	scanf("%d", &n);
	int temp;
	for(int i=1; i<=n; i++) {
		scanf("%d", &temp);
		first[temp] = i;
	}
	while(scanf("%d", &temp) != EOF) {
		second[temp] = 1;
		for(int i=2; i<=n; i++){
		   	scanf("%d", &temp);
			second[temp] = i;
		}
		dp();
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值