您的位置:首页 > 其它

hdu 2159

2016-04-20 20:35 330 查看
题目概述:

某人打游戏升级,还需a点经验,最大忍耐度b,怪有c种,各种杀怪合计不超过d个

每种怪有经验e和消耗忍耐度f两种属性(当然也有算1只怪的属性)

若在忍耐范围能升级,输出最多剩下多少忍耐度,否则输出-1

输入:

第一行是a,b,c,d,后面c行每行是e,f,多组数据到eof为止

输出:

每组数据一行,剩余的忍耐度或-1

样例输入:

10 10 1 10

1 1

10 10 1 9

1 1

9 10 2 10

1 1

2 2

9 10 2 10

1 1

3 2

10 10 1 10

20 1

样例输出:

0

-1

1

4

9

讨论:

1.这里是用的倒序,说好的01正,完全倒呢,暂时不太清楚为何,倒序万能?不对……这其实也是正序吧,倒序哪有用min的

这里一开始尝试过考虑已经杀过的怪的数量,防止在已经限制杀怪数的情况下杀超,不过似乎没有也无所谓,当然了,当时用的是if,不是一行min就能解决的

2.这里最开始用的是==,因为当时以为总是会经验正好够,甚至出的数据也是如此,看了讨论版贡献的数据后才发现问题,这是额的老问题,习惯性恰好,然而还是<=更保险一些,错了好几次呢

另外注意,这里遍历的顺序,列在外层,行在内层,因为要求的是列的数据,这样考虑便是最小

题解状态:

62MS,1948K,1349B,C++

#include<cmath>
#include<cctype>
#include<cstring>
#include<algorithm>
#include<numeric>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<list>
#include<stack>
using namespace std;

struct mon
{
int v;
int c;
mon(int a, int b) :v(a), c(b) {};
};
int cnt;
vector<mon>mons;
vector<vector<int>>pro;
int fun(int value, int ren, int kind, int num)
{
pro.resize(num + 1);
for (int p = 0; p <= num; p++) {
pro[p].resize(ren + 1);
fill(pro[p].begin(), pro[p].end(), value);
}//初始化数组,腾空
for (int p = 0; p < kind; p++) {
int v, c;
scanf("%d%d", &v, &c);//input
mons.push_back(mon{ v,c });
}
for (int p = 0; p < kind; p++) {
for (int i = 1; i <= num; i++) {
for (int u = 0; u <= ren; u++) {
pro[i][u] = min(pro[i][u], u - mons[p].c >= 0 ? pro[i - 1][u - mons[p].c] - mons[p].v : value);//参见讨论1
}
}
}
int p;
if (pro[num][ren] > 0)
p = -1;//如果考虑到最大可能都不行,直接-1吧,不用遍历了
else
for (int u = 0; u <= ren; u++) {
for (int i = 0; i <= num; i++) {
if (pro[i][u] <= 0) {//参见讨论2
p = u;
goto m1;
}
}
}
m1:
;//这一块是遍历数组查找可保留最大忍耐度,原来写的内联函数,后来还是整合
return p == -1 ? -1 : ren - p;
}
int main(void)
{
//freopen("vs_cin.txt", "r", stdin);

int value, lim1, kind, lim2;
while (~scanf("%d%d%d%d", &value, &lim1, &kind, &lim2)) {//input
printf("%d\n", fun(value, lim1, kind, lim2));//output
mons.clear();
pro.clear();
}
}

EOF
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: