2019csp-j t3紀念品解題報告

題目描述: https://www.luogu.org/problem/P5662?contestId=24102

完全揹包問題,因數據量不大,可以先用map二維數組把輸入全存下來。

對某一天來說,把數據處理成完全揹包問題:其中,買某一個物品需多少錢,相當於揹包問題中的weigth

明天該物品價錢-今天當前物品價錢就相當於是價值value。動態規劃求出在當前手裏有的M金幣下,明天都賣掉最多能賺多少,隨後M=M+dp[M]。

/*
T未來天數 N紀念品數量 M現在擁有的金幣數量
*/ 
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
int map[105][105];
struct node{
	int w,v;
//weigth記錄買當前物品需花掉的錢,value記錄能賺多少錢 (下一天的價格-今天的價格) 
}point;
int solve(vector<node>& v,int M){
	int dp[10005]={0};
	int len=v.size();
	if(!v.empty()){
		for(int j=0;j<len;j++){
			for(int i=M;i>=0;i--){//滾動數組,完全揹包 
				int max_tmp=-1;
				int len_tmp=i/v[j].w;
				for(int k=0;k<=len_tmp;k++){
					max_tmp=max(max_tmp,k*v[j].v+dp[i-k*v[j].w]);
					dp[i]=max_tmp;
				}
			}
		}
		return dp[M]+M;
	}else
	return M;
}
vector<node> q;

int main() {
	//數據初始化 
	freopen("jnp1.in","r",stdin);
	int T,N,M,tmp;
	scanf("%d %d %d",&T,&N,&M);
	for(int j=0;j<T;j++){
		for(int i=0;i<N;i++){
			scanf("%d",&map[j][i]);
		}
	}
	//邏輯處理 
	for(int j=0;j<T-1;j++){//注意j的範圍 
		for(int i=0;i<N;i++){
			tmp=map[j+1][i]-map[j][i];//買當前物品到明天能賺多少錢 
			if(tmp>0){//若能賺錢,入隊 
				point.w=map[j][i]; point.v=tmp;
				q.push_back(point);
			}
		}
		M=solve(q,M);//完全揹包,更新一下擁有的最大錢數M 
		q.clear();
	}
	printf("%d\n",M);
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章