ssl2295-暗黑破坏神【dp练习】
題目:
無聊中的小x玩起了Diablo I...
游戲的主人公有n個魔法每個魔法分為若干個等級,第i個魔法有p[i]個等級(不包括0)
每個魔法的每個等級都有一個效果值,一個j級的i種魔法的效果值為w[i][j]
魔法升一級需要一本相應的魔法書
購買魔法書需要金幣,第i個魔法的魔法書價格為c[i]
而小x只有m個金幣(好孩子不用修改器)
你的任務就是幫助小x決定如何購買魔法書才能使所有魔法的效果值之和最大
開始時所有魔法為0級 效果值為0。
Input
第一行 用空格隔開的兩個整數n(0
以下n行 描述n個魔法
第i+1行描述 第i個魔法 格式如下(0
c[i] p[i] w[i][1] w[i][2] ... w[i][p[i]]
Output
第一行輸出一個整數,即最大效果
Sample Input
3 10
1 3 1 2 2
2 3 2 4 6
3 3 2 1 10
Sample Output
11
1
0
3
解題思路
這道題剛開始想了忒久,然后終于做錯了。后來經dalao一指點終于開竅,原來那么簡單。第一行可以用正常的分組背包,接著后面的用一個數組記錄,
如:b[選到的組數][所用的價格]=選的等級。
然后遞歸返回就ok了╮(╯﹏╰)╭是的吧。
然后一切盡在die代碼中
代碼(這次就不用代碼片了):
#include<cstdio>
#include<iostream>
using namespace std;
int b[101][501],c[101],a[101][51],f[101][501],p[101],m,n,ss[501],x,y;
bool flag;
void print(int x,int y)//返回
{
if (x==0) return;//到第1個后返回
print(x-1,y-b[x][y]*c[x]);//遞歸回去
printf("%d\n",b[x][y]);//輸出
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%d%d",&c[i],&p[i]);
for (int j=1;j<=p[i];j++)
{
scanf("%d",&a[i][j]);
}
}
//以上輸入依舊不解釋
for (int i=1;i<=n;i++)
{
?for (int j=1;j<=m;j++)
?{
? ?f[i][j]=f[i-1][j];//繼承上一個
? ?for (int k=0;k<=p[i];k++)
? ?{
? ? ?if (c[i]*k>j) break;//如果當前的價值大于j了則可以退出了
? ? ?if (f[i][j]<f[i-1][j-c[i]*k]+a[i][k])//如果找到更大的
? ? ?{
? ? ? ?f[i][j]=f[i-1][j-c[i]*k]+a[i][k];//替換
? ? ? ?b[i][j]=k;//記錄
? ? ?}
? ?}
?}
}
printf("%d\n",f[n][m]);//輸出最大值
for (int j=m;j>=1;j--)
?for (int i=n;i>=1;i--)//注意遞歸順序(⊙v⊙)
if (f[i][j]>=f[x][y])//注意是>=不是>
{
x=i;
y=j;
}//尋找最大值,讓遞歸次數少些。
print(x,y);//看上面↑
for (int i=x+1;i<=n;i++) printf("0\n");//輸出后面少的那些0
}
總結
以上是生活随笔為你收集整理的ssl2295-暗黑破坏神【dp练习】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 吉利控股集团孙宏:未来几年新能源汽车渗透
- 下一篇: ssl1197-质数和分解【dp练习】