1. 程式人生 > >hihoCoder 1285 [Offer收割]程式設計練習賽3-3

hihoCoder 1285 [Offer收割]程式設計練習賽3-3

[Offer收割]程式設計練習賽3——第3題

這次練習賽感覺比前兩次練習賽簡單一點,第1第2題就不說了。


#1285 : 智力競賽


時間限制: 5000ms 單點時限: 1000ms 記憶體限制: 256MB

描述

小Hi、小Ho還有被小Hi強拉來的小Z,準備組隊參加一個智力競賽。競賽採用過關制,共計N個關卡。在第i個關卡中,小Hi他們需要獲得Ai點分數才能夠進入下一關。每一關的分數都是獨立計算的,即使在一關當中獲得超過需要的分數,也不會對後面的關卡產生影響。

小Hi他們可以通過答題獲得分數。答對一道題獲得S點分數,答錯一道題獲得T點分數。在所有的N個關卡中,小Hi他們一共有M次答題機會。在每個關卡中,都可以在累計答題次數不超過M的情況下使用任意次的答題機會。

那麼現在問題來了,對於給定的N、M、S、T和A,小Hi他們至少需要答對多少道題目才能夠完成所有的關卡呢?

輸入

每個輸入檔案包含多組測試資料,在每個輸入檔案的第一行為一個整數Q,表示測試資料的組數。

每組測試資料的第一行為四個正整數N、M、S和T,意義如前文所述。

第二行為N個正整數,分別表示A1~AN

對於40%的資料,滿足1<=N,M<=100

對於100%的資料,滿足1<=N,M<=1000,1<=T<S<=10,1<=Ai<=50

對於100%的資料,滿足1<=Q<=100

輸出

對於每組測試資料,如果小Hi他們能夠順利完成關卡,則輸出一個整數Ans,表示小Hi他們至少需要答對的題目數量,否則輸出No。

樣例輸入
1
2 10 9 1
12 35 
樣例輸出
5

思路: 明顯是動規。dp[i][j]表示過前i關答對j題時,最少要答錯多少題 感覺dp初始化寫得有點亂,而且狀態轉移也沒有很認真考究邏輯細節,一提交居然直接ac了。。有點小高興

#include<iostream>
#include<string.h>
#include<limits.h>
using namespace std;

#define MAXN 1003
#define MAXM 1003

int dp[MAXN][MAXM];
int a[MAXN];
int n,m,s,t;

int main(){
	int Q,k,p;
	scanf("%d",&Q);
	while(Q--){
		memset(dp,0,MAXM*sizeof(int));
		memset(a,0,sizeof(a));
		scanf("%d%d%d%d",&n,&m,&s,&t);
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
			fill(dp[i],dp[i]+MAXM,INT_MAX);
		}
		for(int i=1;i<=n;i++){
			k=(a[i]+s-1)/s;
			for(int j=0;j<=m;j++){
				for(int h=0;h<=k;h++){
					p=a[i]-h*s;
					p=(p<=0?0:((p+t-1)/t));
					dp[i][j+h]=min(dp[i][j+h],dp[i-1][j]+p);
				}
			}
		}
		bool has=false;
		for(int i=0;i<=m;i++){
			if(i+dp[n][i]<=m){
				has=true;
				cout<<i<<endl;
				break;
			}
		}
		if(!has)
			cout<<"No"<<endl;
	}
}