【动规中的贪心思想】汪老师结婚——婚礼上的袭击

题目:汪老师结婚——婚礼上的袭击 rqnoj303

题目描述

背景:雅礼中学信息组那英俊潇洒风流倜傥身高五尺玉树临风的汪老师要结婚的消息,如一重磅炸弹在众人耳旁炸响。但他的学生们却早已在阴影中悄悄策划了一个天大的阴谋…..
话说汪老师正喜气洋洋的在婚礼上傻笑,突然从门外冲进了N个他的学生:zhangrunzhou、yiming94、jimmyandhxm、pc、zw7840、行云流水、chensqi……大牛们每人手中都拿着一个臭不可闻的鸡蛋,向汪老师掷去。幸好英明神武的汪老师早就安排了间谍(yiming94),于是他老人家不慌不忙地从身后拿出N个刚从地摊上买来的盾牌,以防护学生扔来的臭鸡蛋。但因为各人的力量不同,且汪老师盾牌的质量也不同(谁叫他贪便宜买地摊货),只有汪老师的盾牌防御要高于鸡蛋的攻击力才算防守成功,所以汪老师在选择用哪个盾牌防御哪个鸡蛋的问题上发了愁,更何况汪老师的未婚妻还在一旁看着,汪老师每被击中一次,她对汪老师的好感就会下降200点;而每当汪老师成功防住一次,她对汪老师的好感就会上升200点(如果防御等于攻击,她对汪老师的好感不升也不降)。于是汪老师找来了智慧超群zrp,请他来帮着算一下怎样才能使汪老师的未婚妻对汪老师的好感最高。但由于zrp急着准备初二的生地会考,所以就只好请你来帮忙算一下。(汪老师的未婚妻的初始好感值为零,一个盾牌只能用一次)

输入格式

第一行一个数n 范围 n<=100000 以0结束 n表示汪老师的盾牌数量
第二行输入汪老师的n个盾牌的防御力
第三行大牛们的攻击力
(一次输入多组数据,当n为0时结束)

输出格式

一个数:汪老师未婚妻的好感(可能为负数)

样例输入

样例输出

 

这一题和田忌赛马一体差不多,只是换了一个背景

先进行一次快排,将盾牌和攻击排序,然后一次预处理,处理出任意两个之间的代价g[i,j],但是此题规模太大,所以预处理不能用g[i,j]数组来存,只能每枚举一次,进行一次预处理,算出当前代价

f[i,j]维护f[区间起始位置,区间长度],由于空间不够,所以区间长度改成01滚动

剩下的就枚举每一种情况就行了

C++ Code

#include<cstdio>
#include<string>
using namespace std;
#define MAXN 100010

int n,fs[MAXN],g[MAXN],f[MAXN][2];//f[区间起始位置][区间长度] //01滚动

void qs(int a[],int l,int r)
{
  int i=l,j=r,x=a[i+(j-i)/2];
  do
  {
    while(a[i]>x)i++;
    while(a[j]<x)j--;
    if(i<=j)
    {
      swap(a[i],a[j]);
      i++;j--;
    }
  }
  while(i<=j);
  if(i<r)qs(a,i,r);
  if(l<j)qs(a,l,j);
}

void predoing()
{
  int i,j;
  qs(fs,1,n);//其实这里可以直接调用sort(fs+1,fs+1+n);  下面同理
  qs(g,1,n);
}

int main()
{
  freopen("rqn303.in","r",stdin);
  freopen("rqn303.out","w",stdout);
  int i,j,t,co;
  while(scanf("%d",&n))
  {
    if(n==0)exit(0);
    for(i=1;i<=n;i++) scanf("%d",&fs[i]);
    for(i=1;i<=n;i++) scanf("%d",&g[i]);
    predoing();
    t=0;
    for(i=1;i<=n;i++)
    {
      if(fs[i]<g[n])f[i][t]=-200;
      if(fs[i]>g[n])f[i][t]=200;
      if(fs[i]==g[n])f[i][t]=0;
    }
    t=1-t;
    for(j=2;j<=n;j++,t=1-t)
      for(i=1;i<=n-j+1;i++)
      {
        if(fs[i]>g[n-j+1])co=200;
        if(fs[i]<g[n-j+1])co=-200;
        if(fs[i]==g[n-j+1])co=0;
        
        f[i][t]=co+f[i+1][1-t];
        
        if(fs[i+j-1]>g[n-j+1])co=200;
        if(fs[i+j-1]<g[n-j+1])co=-200;
        if(fs[i+j-1]==g[n-j+1])co=0;
        
        if(f[i][t]<co+f[i][1-t])f[i][t]=co+f[i][1-t];
      }
    printf("%d\n",f[1][1-t]);
  }
  return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值