HDU - 6396 Swordsman (单调性+贪心)
题意:有n个怪物和k种属性,当且仅当你的每种属性都大于等于怪物的属性才可以击杀它,且击杀怪物可以提升你一定的属性值。求可击杀怪物的最大数量以最终的属性值。
这不就是银行家算法里的安全性检验么?
本题的时限比较严,需要用fread来加速读入
第一种做法是对每种属性建一个优先队列,每个优先队列里存放怪物编号以及对应的属性值,属性值越低的优先级越高。首先把所有怪物放进第一个优先队列,然后循环检查。如果你的该种属性值比怪物大,那么把怪物弹出再放入下一个优先队列,...,如此往复。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=1e5+10,inf=0x3f3f3f3f; 5 struct D { 6 int i,x; 7 bool operator<(const D& b)const {return x>b.x;} 8 }; 9 priority_queue<D> q[5]; 10 int a[N][5],n,k,b[5],c[N][5],tot,p; 11 char buf[(int)4e7]; 12 void init() {p=0,tot=fread(buf,1,(int)4e7,stdin);} 13 void read(int& x) { 14 x=0; 15 for(; p<tot&&!isdigit(buf[p]); ++p); 16 for(; p<tot&&isdigit(buf[p]); ++p)x=x*10+buf[p]-'0'; 17 } 18 int main() { 19 init(); 20 int T; 21 for(read(T); T--;) { 22 read(n),read(k); 23 for(int i=0; i<k; ++i)while(q[i].size())q[i].pop(); 24 for(int i=0; i<k; ++i)read(b[i]); 25 for(int i=0; i<n; ++i) { 26 for(int j=0; j<k; ++j)read(a[i][j]); 27 for(int j=0; j<k; ++j)read(c[i][j]); 28 } 29 for(int i=0; i<n; ++i)q[0].push({i,a[i][0]}); 30 int ans=0; 31 while(1) { 32 int cnt=0; 33 for(int i=0; i<k; ++i) { 34 for(; q[i].size()&&q[i].top().x<=b[i]; q[i].pop()) { 35 int t=q[i].top().i; 36 if(i==k-1) { 37 for(int j=0; j<k; ++j)b[j]+=c[t][j]; 38 ++cnt; 39 } else q[i+1].push({t,a[t][i+1]}); 40 } 41 } 42 if(!cnt)break; 43 ans+=cnt; 44 } 45 printf("%d\n",ans); 46 for(int i=0; i<k; ++i)printf("%d%c",b[i]," \n"[i==k-1]); 47 } 48 return 0; 49 }
第二种做法是把所有怪物分别按照k种属性的递增序排序,并设置k个指针,从头到尾进行扫描。如果某个怪物被扫到了k次,那么这只怪物就被成功击杀。循环进行即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=1e5+10,inf=0x3f3f3f3f; 5 struct D { 6 int i,x; 7 bool operator<(const D& b)const {return x<b.x;} 8 } d[5][N]; 9 int a[N][5],n,k,b[5],c[N][5],tot,p,m[5],sz[N]; 10 char buf[(int)4e7]; 11 void init() {p=0,tot=fread(buf,1,(int)4e7,stdin);} 12 void read(int& x) { 13 x=0; 14 for(; p<tot&&!isdigit(buf[p]); ++p); 15 for(; p<tot&&isdigit(buf[p]); ++p)x=x*10+buf[p]-'0'; 16 } 17 int main() { 18 init(); 19 int T; 20 for(read(T); T--;) { 21 read(n),read(k); 22 for(int i=0; i<k; ++i)read(b[i]); 23 for(int i=0; i<n; ++i) { 24 for(int j=0; j<k; ++j)read(a[i][j]),d[j][i]= {i,a[i][j]}; 25 for(int j=0; j<k; ++j)read(c[i][j]); 26 sz[i]=0; 27 } 28 for(int i=0; i<k; ++i)sort(d[i],d[i]+n),m[i]=0; 29 int ans=0; 30 while(1) { 31 int cnt=0; 32 for(int i=0; i<k; ++i) { 33 for(; m[i]<n&&d[i][m[i]].x<=b[i]; ++m[i]) { 34 int t=d[i][m[i]].i; 35 if(++sz[t]==k) { 36 for(int j=0; j<k; ++j)b[j]+=c[t][j]; 37 ++cnt; 38 } 39 } 40 } 41 if(!cnt)break; 42 ans+=cnt; 43 } 44 printf("%d\n",ans); 45 for(int i=0; i<k; ++i)printf("%d%c",b[i]," \n"[i==k-1]); 46 } 47 return 0; 48 }