UVALive - 6952 Cent Savings dp
题目链接:
http://acm.hust.edu.cn/vjudge/problem/116998
Cent Savings
样例
sample input
5 1
13 21 55 60 42
5 2
1 1 1 1 1sample output
190
0
题意
给你一个数组,现在要把它最多切d刀分成d+1块,对每一块的和要四舍五入,问如果分割使得最后的和最大。
题解
各种姿势的dp:
dp[i][j][k]表示前i个,切了j刀,最后一刀切完之后的值%10为k的舍入的最大偏差。
则最后的结果=min(sum-dp[n][j][k])。
#include<map>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII;
const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const int maxn=2222;
int n,d;
int arr[maxn];
int dp[maxn][22][11];
inline int f(int x){
if(x<5) return x;
else return x-10;
}
int main() {
while(scanf("%d%d",&n,&d)==2){
rep(i,0,maxn) rep(j,0,22) rep(k,0,11) dp[i][j][k]=-INF;
dp[0][0][0]=0;
int sum=0;
rep(i,1,n+1){
scanf("%d",&arr[i]);
sum+=arr[i];
}
rep(i,0,n){
rep(j,0,d+1){
rep(k,0,10){
int nk=(arr[i+1]+k)%10;
dp[i+1][j][nk]=max(dp[i+1][j][nk],dp[i][j][k]-f(k)+f(nk));
nk=arr[i+1]%10;
if(j+1<=d) dp[i+1][j+1][nk]=max(dp[i+1][j+1][nk],dp[i][j][k]+f(nk));
}
}
}
int ma=f(sum%10);
rep(j,0,d+10){
rep(k,0,10){
ma=max(ma,dp[n][j][k]);
}
}
printf("%d\n",sum-ma);
}
return 0;
}
dp[i][j]表示前i个切了j刀得到的最小和(刀切在i后面或不切)。
#include<map>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define pb(v) push_back(v)
#define sz() size()
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII;
const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
//start----------------------------------------------------------------------
const int maxn=2222;
const int maxm=22;
int n,d;
int dp[maxn][maxm];
int arr[maxn];
int f(int x){
int t=x%10;
if(t>=5) x+=10;
x-=t;
return x;
}
int main() {
while(scanf("%d%d",&n,&d)==2){
clr(dp,0x3f);
dp[0][0]=0;
rep(i,1,n+1) scanf("%d",&arr[i]);
rep(i,1,n){
rep(j,0,d+1){
if(j==0) dp[i][j]=dp[i-1][j]+arr[i];
else dp[i][j]=min(dp[i-1][j]+arr[i],f(dp[i-1][j-1]+arr[i]));
}
}
int ans=INF;
rep(j,0,d+1) ans=min(ans,f(dp[n-1][j]+arr[n]));
printf("%d\n",ans);
}
return 0;
}
//end-----------------------------------------------------------------------
dp[i][j]表示前i个切了j刀得到的最小和
#include<map>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define pb(v) push_back(v)
#define sz() size()
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII;
const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const int maxn=2222;
const int maxm=22;
int n,d;
int dp[maxn][maxm];
int arr[maxn],sumv[maxn];
int f(int x){
int t=x%10;
if(t>=5) x+=10;
x-=t;
return x;
}
int main() {
while(scanf("%d%d",&n,&d)==2){
clr(dp,0x3f);
dp[0][0]=0; sumv[0]=0;
rep(i,1,n+1){
scanf("%d",&arr[i]);
sumv[i]=sumv[i-1]+arr[i];
dp[i][0]=f(sumv[i]);
}
rep(i,1,n+1){
rep(j,1,d+1){
rep(k,0,i){
dp[i][j]=min(dp[i][j],dp[k][j-1]+f(sumv[i]-sumv[k]));
}
}
}
int ans=f(sumv[n]);
rep(j,1,d+1) ans=min(ans,dp[n][j]);
printf("%d\n",ans);
}
return 0;
}