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 }

 

posted @ 2019-06-28 08:20  jrltx  阅读(168)  评论(0编辑  收藏  举报