PKU 2642-The Brick Stops Here

問題概要

1000gの煉瓦がいくつかある.それぞれの銅の含有量と価格があたえられたとき,
m個の煉瓦を持ちいて,銅の含有量がcmin以上cmax以下の煉瓦を作る時の最安値を求めよ

解法

動的計画法.煉瓦はn個あるとして,銅の含有量をw[i],価格をc[i]とし,
dp[x][y]をy個の煉瓦に対してx[g]の銅を含有量の合計の時の最安値とすることで,
k番目の品物に対して,
dp[i][j]=min(dp[i-w[k]][j]+c[k],dp[i][j])
が成り立つ.

実装(C++)

#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
using namespace std;

typedef long long int lli;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define rep(i,s,x) for(int i=s;i<(int)(x);i++)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RREP(i,x) for(int i=(x);i>=0;i--)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
int N,M;
int weight[200],price[200];
int dp[20001][21];//i[g]のものをj個使って作るときの最安値
int main(){
	cin>>N;
	REP(i,N){
		cin>>weight[i]>>price[i];
	}
	memset(dp,0x3F,sizeof(dp));
	dp[0][0]=0;

	for(int k=0;k<N;k++){
		for(int i=20000;i>=0;i--){
			if(i-weight[k]<0)break;
			for(int j=0;j<20;j++){
				dp[i][j+1]=min(dp[i][j+1],dp[i-weight[k]][j]+price[k]);
			}
		}
	}
	int c;
	cin>>c;
	int m,cmin,cmax;
	REP(i,c){
		cin>>m>>cmin>>cmax;
		int ans=0x7FFFFFFF;
		for(int i=cmin*m;i<=cmax*m;i++){
			ans=min(ans,dp[i][m]);
		}
		if(ans>0x2F3F3F3F){
			cout<<"impossible"<<endl;
		}else{
			cout<<ans<<endl;
		}
	}
}