首页 > 代码库 > 【58测试】【贪心】【离散】【搜索】【LIS】【dp】
【58测试】【贪心】【离散】【搜索】【LIS】【dp】
第一题 大天使之剑 大意:
有n个怪,每个怪的ph 为 h[i],有三种攻击方式,普通攻击:一次打一个怪一滴血;重击(消耗1魔法值):一次打一个怪两滴血;群体攻击(消耗1魔法值):一次打所有怪一滴血。你有无数血,m个魔法值,每攻击一次怪后,还存活的所有怪会各攻击你一滴血。问你打完所有怪你最少被打了多少滴血。
解:
看到这道题,首先想到的是搜索,一种一种的搜,把所有情况都搜出来找最小。在草稿纸上再列一些数据就会发现,其实是个贪心。在有魔法值的时候,尽量全用于群体攻击更划算,然后没有了就普通攻击。那重击呢?由于我的数据比较特殊,所以我判重击的条件是还剩两个偶数滴血的怪,但其实,不管它的血量是偶数还是奇数,重击都更划算。还有一些杂七杂八的减没减过sum的问题等,让我调试了一个下午。看来以后静态查错很重要,少犯小错误。代码写得丑。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 100005 6 #define ll long long 7 using namespace std; 8 ll n,m,ph[maxn],ans,sum,cur=1; 9 bool jian[maxn];10 void print()11 {12 printf("%I64d",ans);13 return ;14 }15 int main()16 {17 freopen("zhijian.in","r",stdin);18 freopen("zhijian.out","w",stdout);19 cin>>n>>m;20 for (int i=1;i<=n;i++)21 scanf("%d",&ph[i]);22 sort(ph+1,ph+1+n);23 while (m)24 {25 if (n-cur+1<=2){//改用重击26 for (int i=cur;i<=n;i++)27 if (!jian[i]) ph[i]-=sum;28 while(m){29 if (cur>n) {30 print();return 0;31 }32 if (ph[cur]<=2){33 ans+=n-cur;34 cur++;continue;35 }36 ph[cur]-=2;37 ans+=n-cur+1;38 m--;39 }40 while (cur<=n){41 if (ph[cur]){42 int ci=ph[cur]-1;43 ans+=(n-cur+1)*ci;44 }45 ans+=n-cur;46 cur++;47 }48 print();49 return 0;50 }51 sum++;52 ph[cur]--;int h=cur;53 jian[cur]=true;54 ans+=n-cur+1;55 while (ph[cur]<=0){56 ans--;57 cur++;58 ph[cur]-=sum;59 jian[cur]=true;//判断 60 }61 m--;62 }63 while (cur<=n){64 if (!jian[cur]) ph[cur]-=sum;//直接减会多减 65 if (ph[cur]){66 int ci=ph[cur]-1;67 ans+=(n-cur+1)*ci;68 }69 ans+=n-cur;70 cur++;71 }72 printf("%I64d",ans);73 return 0;74 }
第二题 保卫萝卜 大意:
一个很大的矩阵,起点在正中心的方格。数据有向上下左右四个方向走的记录,输出走过的方格及所围的方格数。
解:
有两种大体思路。一个是直接正着算面积,还有反着算走不到的点。我用的后者。但有一个问题,就是存矩阵。我把它走过的地方的最左边上面下面和右边记录下来,然后在这个包含它走的所有路的方格中从0,0开始遍历dfs,到不了的地方vis=false,即为ans++。注意要在搜索范围中再加一圈,因为可能走过的路把这个范围隔开了,就搜索不到。但这是60分的做法,100分做法要用离散化坐标的思想,先放一下。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 2005 6 using namespace std; 7 const int zl[2][4]={{0,0,1,-1},{1,-1,0,0}}; 8 int n,xi,yi,idx,sum,ans; 9 bool mp[maxn][maxn],vis[maxn][maxn];10 int uup,don,le,ri,stx,sty;11 struct pp{12 int x,y;13 };14 pp tur[1005];15 char c[1005];16 void dfs(int xx,int yy)17 {18 for (int i=0;i<=3;i++)19 {20 int ki=xx+zl[0][i],kj=yy+zl[1][i];21 if (ki>=0&&kj>=0&&ki<=ri&&kj<=uup&&!vis[ki][kj]&&!mp[ki][kj])22 {23 vis[ki][kj]=true;24 sum++;dfs(ki,kj);25 }26 }27 }28 int main()29 {30 freopen("luobo.in","r",stdin);31 freopen("luobo.out","w",stdout);32 cin>>n;33 getchar();34 for (int i=1;i<=n;i++)35 {36 c[i]=getchar();37 getchar();int a;38 scanf("%d",&a);39 if (c[i]==‘L‘) {stx-=a;if (stx<le) le=stx;}40 else if (c[i]==‘R‘){stx+=a;if (stx>ri) ri=stx;}41 else if (c[i]==‘U‘) {sty+=a;if (sty>uup) uup=sty;}42 else if (c[i]==‘D‘){sty-=a;if (sty<don) don=sty;}43 tur[++idx].x=stx;tur[idx].y=sty;44 getchar();45 }46 xi=-le+1;yi=-don+1;uup+=-don+2;ri+=-le+2;47 mp[xi][yi]=true;48 for (int i=1;i<=idx;i++)49 {50 tur[i].x+=-le+1;tur[i].y+=-don+1;51 int a=min(xi,tur[i].x),b=max(xi,tur[i].x),ci=min(yi,tur[i].y),d=max(yi,tur[i].y);52 for (int j=a;j<=b;j++)53 for (int k=ci;k<=d;k++)54 mp[j][k]=true;55 xi=tur[i].x;yi=tur[i].y;56 }57 dfs(0,0);58 for (int i=0;i<=ri;i++)59 for (int j=0;j<=uup;j++)60 if (!vis[i][j]) ans++;61 printf("%d",ans);62 return 0;63 }
第三题 打地鼠 大意:
(没错怎么都是游戏的名字)打地鼠,打的这个地鼠的肥胖值一定要比上一个打的大。地鼠最多出现t次,问最多能打多少地鼠。
解:
看起来是个简单的最长上升序列。但是有一个t次,所以直接扫描加一个循环t就可以了,是不影响的。然后LIS 的nlogn的算法才能过这道题。具体的解释我觉得这个博客讲的就很清楚。http://blog.csdn.net/shuangde800/article/details/7474903
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 100005 6 using namespace std; 7 int n,maxx,k,t,a[maxn],d[maxn],ans; 8 int main() 9 {10 freopen("dishu.in","r",stdin);11 freopen("dishu.out","w",stdout);12 cin>>k>>n>>maxx>>t;13 while (k--)14 {15 memset(d,0,sizeof(d));16 int idx;ans=0;17 for (int i=1;i<=n;i++)18 scanf("%d",&a[i]);19 d[1]=a[1];ans=1;20 for(int i=1;i<=t;i++)21 for (int j=1;j<=n;j++)22 {23 if (a[j]>d[ans]) d[++ans]=a[j];24 else {25 int pos=lower_bound(d+1,d+1+ans,a[j])-d;//-d not -d-1 ?26 d[pos]=a[j];27 }28 }29 printf("%d\n",ans);30 }31 return 0;32 }
好好睡一觉,明天联考加油,不要有压力。
【58测试】【贪心】【离散】【搜索】【LIS】【dp】