D - FATE HDU-2159 FATE 二維背包
Description
最近xhd正在玩一款叫做FATE的遊戲,為了得到極品裝備,xhd在不停的殺怪做任務。久而久之xhd開始對殺怪產生的厭惡感,但又不得不通過殺怪來升完這最後一級。現在的問題是,xhd升掉最後一級還需n的經驗值,xhd還留有m的忍耐度,每殺一個怪xhd會得到相應的經驗,並減掉相應的忍耐度。當忍耐度降到0或者0以下時,xhd就不會玩這遊戲。xhd還說了他最多只殺s只怪。請問他能升掉這最後一級嗎?Input
Output
輸出升完這級還能保留的最大忍耐度,如果無法升完這級輸出-1。Sample Input
10 10 1 10 1 1 10 10 1 9 1 1 9 10 2 10 1 1 2 2Sample Output
0 -1 1 這個題目我先想直接通過自己的理解來解題,大概是標記一個數量,然後根據背包的情況不斷更改這個值的數量,只是中間的這種考慮針對有些情況是不合適的,所以經典的問題的一般性模擬,有時候還是有一些困難的。 這是錯誤的代碼:#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct dp_node
{
int value;
int total_num;
};
struct dp_node dp[105][105];
struct node
{
int tolerate;
int exp;
double rati;
friend bool operator<(node a,node b)
{
return a.rati>b.rati;
}
};
struct node num[105];
int main()
{
int n,m,k,s;
while(scanf("%d%d%d%d",&n,&m,&k,&s)!=EOF)
{
for(int i=1;i<=k;i++)
{
scanf("%d%d",&num[i].exp,&num[i].tolerate);
num[i].rati=num[i].exp*1.0/num[i].tolerate;
}
// sort(num,num+k);
for(int j=0;j<105;j++)
{
dp[0][j].value=0;
dp[0][j].total_num=0;
dp[j][0].value=0;
dp[j][0].total_num=0;
}
for(int i=1;i<=k;i++)
{
for(int j=num[i].tolerate;j<=m;j++)
{
dp[i][j].value=dp[i-1][j].value;
dp[i][j].total_num=dp[i-1][j].total_num;
for(int ak=0;ak<=j/num[i].tolerate;ak++)
{
if(dp[i][j].value<dp[i-1][j-ak*num[i].tolerate].value+ak*num[i].exp)
{
dp[i][j].value=dp[i-1][j-ak*num[i].tolerate].value+ak*num[i].exp;
dp[i][j].total_num=dp[i-1][j-ak*num[i].tolerate].total_num+ak;
}
}
}
}
for(int i=0;i<=m;i++)
{
// printf("%d\n",dp[k][i].value);
if(dp[k][i].value>=n&&dp[k][i].total_num<=s)
{
printf("%d\n",m-i);
break;
}
if(i==m)
{
printf("-1\n");
}
}
}
return 0;
}
然後,後面用二維擴展背包,果然一下就過了,所以有時候,經典的問題,還是有其一般性與特點的。
這個的一般性主要體現在第二重循環中,通過這個循環很好的解決了一般性問題,同時也強掉了狀態轉移方程的重要性。
這時正確的代碼:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
int tolerate;
int exp;
double rati;
friend bool operator<(node a,node b)
{
return a.rati>b.rati;
}
};
struct node num[105];
int dp[105][105];
int main()
{
int n,m,k,s;
while(scanf("%d%d%d%d",&n,&m,&k,&s)!=EOF)
{
for(int i=1;i<=k;i++)
{
scanf("%d%d",&num[i].exp,&num[i].tolerate);
num[i].rati=num[i].exp*1.0/num[i].tolerate;
}
memset(dp,0,sizeof(dp));
for(int i=1;i<=k;i++)
{
for(int j=num[i].tolerate;j<=m;j++)
{
for(int ak=1;ak<=s;ak++)
{
if(dp[j][ak]<dp[j-num[i].tolerate][ak-1]+num[i].exp)
dp[j][ak]=dp[j-num[i].tolerate][ak-1]+num[i].exp;
}
}
}
for(int i=0;i<=m;i++)
{
if(dp[i][s]>=n)
{
printf("%d\n",m-i);
break;
}
if(i==m)
printf("-1\n");
}
}
return 0;
}
D - FATE HDU-2159 FATE 二維背包