[DP]UVa 10003 Cutting Sticks

2 篇文章 0 订阅
1 篇文章 0 订阅

记忆化搜索

#include<bits/stdc++.h>
#define debug(x) cout<<#x<<" is "<<x<<endl
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define DBG 0
//const int N = 1e5 + 5;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const ll LLINF = (1LL<<60);
using namespace std;
const int mod = 998244353;
ll fast_pow(ll a,ll b){
	ll ans = 1;
	while(b){
		if(b&1)ans = (ans * a)%mod;
		a = (a * a)%mod;
		b>>=1;
	}
	return (ans%mod);
}
typedef pair<int,int> pii;
const int N = 55;
int dp[N][N];
int l,n;
int a[N];
int dfs(int l,int r){
	if(dp[l][r] != INF)return dp[l][r];
	if(l == r - 1)return 0;
	int ans = INF;
	for(int i = l + 1;i < r;i++)
		ans = min(dfs(l,i) + dfs(i,r) + a[r]- a[l],ans);
	dp[l][r] = ans;
	//cout<<"L : "<<l<<" R :  "<<r<<"    "<<dp[l][r]<<endl;
	return ans;
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
#if DBG
	freopen("input.txt","r",stdin);
#endif
	while(cin>>l){
		if(l == 0)break;
		cin>>n;
		for(int i = 2;i <= n + 1;i++)cin>>a[i];
		for(int i = 1;i <= n + 2;i++)
			for(int j = 1;j <= n + 2;j++)dp[i][j] = INF;
		a[1] = 0,a[n + 2] = l;
		printf("The minimum cutting is %d.\n",dfs(1,n + 2));
	}
	return 0;
}

递推思路:
对一个长的区间,需要事先知道比它短的区间的最优解,才能更新这个长的区间,因此,可以根据区间长度枚举。

#include<bits/stdc++.h>
#define debug(x) cout<<#x<<" is "<<x<<endl
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define DBG 0
const int N = 50 + 5;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const ll LLINF = (1LL<<60);
using namespace std;
const int mod = 998244353;
ll fast_pow(ll a,ll b){
	ll ans = 1;
	while(b){
		if(b&1)ans = (ans * a)%mod;
		a = (a * a)%mod;
		b>>=1;
	}
	return (ans%mod);
}
typedef pair<int,int> pii;
int dp[N][N];
int a[N];
int l,n;
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
#if DBG
	freopen("input.txt","r",stdin);
#endif
	while(cin>>l){
		if(l == 0)break;
		cin>>n;
		for(int i = 1;i <= n + 2;i++)for(int j = 1;j <= n+ 2;j++)dp[i][j] = INF;
		for(int i = 2;i <= n + 1;i++){
			cin>>a[i];
			dp[i - 1][i] = 0;
		}
		a[1] = 0,a[n + 2] = l;
		dp[n + 1][n + 2] = 0;
		for(int len = 2;len <= n + 1;len++){
			for(int i = 1;i + len <= n + 2;i++){
				for(int j = i + 1;j < i + len;j++){
					dp[i][i + len] = min(dp[i][i + len],dp[i][j] + dp[j][i + len] + a[i + len] - a[i]);
					//cout<<"L : "<<i<<" R : "<<i + len <<"   "<<dp[i][i + len]<<endl;
				}
			}
		}
		printf("The minimum cutting is %d.\n",dp[1][n + 2]);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值