UVALive - 6952 Cent Savings dp

题目链接:

http://acm.hust.edu.cn/vjudge/problem/116998

Cent Savings

Time Limit: 3000MS
#### 问题描述 > To host a regional contest like NWERC a lot of > preparation is necessary: organizing rooms and > computers, making a good problem set, inviting > contestants, designing T-shirts, booking hotel > rooms and so on. I am responsible for going > shopping in the supermarket. > When I get to the cash register, I put all my > n items on the conveyor belt and wait until all > the other customers in the queue in front of me > are served. While waiting, I realize that this > supermarket recently started to round the total > price of a purchase to the nearest multiple of 10 > cents (with 5 cents being rounded upwards). For > example, 94 cents are rounded to 90 cents, while > 95 are rounded to 100. > It is possible to divide my purchase into groups and to pay for the parts separately. I managed to > find d dividers to divide my purchase in up to d + 1 groups. I wonder where to place the dividers to > minimize the total cost of my purchase. As I am running out of time, I do not want to rearrange items > on the belt. #### 输入 > The input file contains several test cases, each of them as described below. > The input consists of: > • one line with two integers n (1 ≤ n ≤ 2000) and d (1 ≤ d ≤ 20), the number of items and the > number of available dividers; > • one line with n integers p1, . . . , pn (1 ≤ pi ≤ 10000 for 1 ≤ i ≤ n), the prices of the items in > cents. The prices are given in the same order as the items appear on the belt. #### 输出 > For each test case, output the minimum amount of money needed to buy all the items, using up to d > dividers.

样例

sample input
5 1
13 21 55 60 42
5 2
1 1 1 1 1

sample 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;
}
posted @ 2016-08-08 22:43  fenicnn  阅读(208)  评论(0编辑  收藏  举报