题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6396
本题解全部“改编”“抄袭”自IGVA大佬的博客:https://blog.csdn.net/LSD20164388/article/details/81637550
题意:一个剑客有k种属性,有n个怪物每个怪物也有k种属性与k种加成,如果剑客的每种属性都大于某个怪物的对应属性,那么剑客将杀死此怪物,而且剑客的每种属性都要加上此怪物对应的加成,问剑客最终能杀死几个怪物和最终剑客的每种属性值。
解析:
思路:优先队列。用k个优先队列(队列存一个pair存<属性值,怪物编号>,默认按第一个排序,设置升序),队列q[i]是存放怪物的第i种属性。首先把所有怪的第1个属性和怪的编号(用pair)加入到第一个队列当中。每次外层循环查询所有队列(第一个到第m个队列),即从第1个属性开始到第m个属性,如果当前属性小于等于你的属性,就把这个怪的下一个属性和怪的编号加入到下一个优先队列中。直到最后一个优先队列中对应的属性小于等于你的最后一个属性,就累加吃掉这个怪你能提高的每个属性的值。然后此时你的各项属性都已经提高,再重复此操作直到吃掉的怪数不再变化。然而这样还是会TLE。需要抄一个超神输入挂。
优先队列用法:https://blog.csdn.net/pzhu_cg_csdn/article/details/79166858
代码:
//IGVA
#include<bits/stdc++.h>
#define ll long long
using namespace std;
namespace fastIO
{
#define BUF_SIZE 100000
//fread -> read
bool IOerror = 0;
inline char nc()
{
static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
if(p1 == pend)
{
p1 = buf;
pend = buf + fread(buf, 1, BUF_SIZE, stdin);
if(pend == p1)
{
IOerror = 1;
return -1;
}
}
return *p1++;
}
inline bool blank(char ch)
{
return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
}
inline void read(int &x)
{
char ch;
while(blank(ch = nc()));
if(IOerror) return;
for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
}
#undef BUF_SIZE
};
using namespace fastIO;
// void read(int &x){scanf("%d",&x);} //调试的时候用这个,把上面的注释掉。
const int maxn=100010;
int n,m,k,a[maxn][10],b[maxn][10],v[maxn];
typedef pair<int, int> pp;
typedef priority_queue< pp, vector<pp>, greater<pp> > QQ;//队列只存放pp一个值
QQ q[10],p;
int main()
{
int T,cas=1;
read(T);
while(T--)
{
read(n);
read(m);
for(int i=0; i<m; i++) read(v[i]);
for(int i=0; i<m; i++) q[i]=QQ();
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
read(a[i][j]);
q[0].push({a[i][0],i});
for(int j=0; j<m; j++)
read(b[i][j]);
}
int ans=0,tmp=-1;
while(tmp!=ans)//ans有更新时继续循环,因为吃掉怪物是自己属性有更新所以这里要循环
{
tmp=ans;
for(int i=0; i<m-1; i++)//处理前m-1种属性,q[i]是存放怪物的第i种属性
{
while(!q[i].empty()&&q[i].top().first<=v[i])//处理对于第i种属性能解决的怪物
{
int x=q[i].top().second;
q[i].pop();
q[i+1].push({a[x][i+1],x});
}
}
while(!q[m-1].empty()&&q[m-1].top().first<=v[m-1])//处理最后一种属性,此时可能有怪物被杀死
{
int x=q[m-1].top().second;
q[m-1].pop();
++ans;
for(int i=0; i<m; i++)
v[i]+=b[x][i];
}
}
int flag=1;
printf("%d\n",ans);
for(int i=0; i<m; i++)
if(flag)
{
flag=0;
printf("%d",v[i]);
}
else printf(" %d",v[i]);
puts("");
}
return 0;
}