`

tyvj 1348 清理内奸

    博客分类:
  • ACM
 
阅读更多
清理内奸


描述 Description  
最近FF博士在玩一个游戏“三国杀杀杀”,他扮演一个英明的主公,四处清剿反贼。终于把反贼全部干掉了,可是他的手下还存在着一些内奸

。经过他的观察和研究,终于发现了内奸的重要特征。内奸最重要的工作就是传递情报,所以内奸必须掌握各种加密方法。于是他们对素数有

一种偏好,编号是素数的人全部是内奸。FF博士将指挥忠臣干掉内奸。忠臣和内奸排成一排,第i个人的编号为Bi。杀死内奸会获得一定量经验

,等级为X的忠臣杀死任意等级的内奸会获得X点经验。每个人都有一定的攻击范围,若站在i位置的人攻击范围为k那么他可以杀[i-k,i+k]范围

内的人,但是每个人都只有一次攻击的机会。内奸们并不知道自己的身份已经暴露,不会攻击任何人,只能做待宰的羔羊,FF博士确定了攻击

方案后会在瞬间下令让忠臣行动,内奸会被秒(也就是内奸死亡不会对原来攻击范围造成影响)。
请帮FF博士计算
1、他这次最多能干掉多少内奸呢?
2、在干掉内奸人数最多的情况下,他能获得最多多少经验?

输入格式 Input Format 
第一行一个数字n,代表FF博士手下有n个人
第二行n个数,第i个数代表第i个人的编号Bi
3~n+2行,每行2个数x,k分别代表第i个人的等级和攻击范围。

输出格式 Output Format 
第一行是FF博士最多能干掉的内奸数量
第二行是FF博士在干掉最多内奸的基础上能获得的最多经验数。

样例输入 Sample Input  
7
1 2 3 4 5 6 8
1 1
3 1
4 1
5 2
10 5
1 1
0 100

样例输出 Sample Output  
3
7

时间限制 Time Limitation 
1S

注释 Hint 
样例解释
第2、3、5个人是内奸 (第7个不是,他的编号为8)
1杀2,获得1点经验
4杀3,获得5点经验
6杀5,获得1点经验
数据范围
对于100%的数据
n<=1000
Bi<=10^7
x,k<=100
所有数据不会出现负数。

分析:“这题其实很容易看出来,n个人分成了2个阵营。每个忠臣与他攻击范围内的内奸连一条边。此题第一问就是求二分图的最大匹配。第

二问是个贪心,权值在点上而不是在边上,所以按等级排序,优先满足等级高的忠臣。因为他一旦匹配成功,就不会被换下来。由于最大匹配

数肯定是确定的,所以让等级高的优先匹配并不会影响结果。”即对于二分原图得到的两个图,若两个子图内的元素之间不存在边,那么确定

一个图,另外一个图中的元素任意改变顺序,都不会影响到最大匹配,所以第二问中只要优先满足等级高的忠臣就可以得到正解。

小结:二分图的最大匹配+贪心(排序应该不是问题)
#include <iostream>
#include <algorithm>
#include <memory.h>
using namespace std;
const int maxn = 1010;
struct person 
{
    int pno;//编号 
    int grade;//等级
    int range;//攻击范围 
    bool isPrime;//编号是否为素数 
    int cno;
};
struct node
{
    int index;//下标
    int grade; 
};
person p[maxn];
node x[maxn];
int n;
int white,black;
bool cmp(node a,node b)
{
    return a.grade>b.grade;
}
bool isPrime(int k)
{
    if(k==1)     return false;
    if(k==2)     return true;
    for(int i=2;i*i<=k;i++)
    {
        if(k%i==0)         return false;
    }
    return true;
}
int adjl[maxn][maxn];
int matx[maxn];
int maty[maxn];
int used[maxn];
int match;
bool find(int k)
{
    for(int i=1;i<=adjl[k][0];i++)
    {
        int j=adjl[k][i];
        if(!used[j])
        {
            used[j]=1;
            if(maty[j]==-1||find(maty[j]))    
            {
               maty[j]=k;
               matx[k]=j;
               return true;
            }
        }
    }
    return  false;
}
void hungary()
{
     for(int i=0;i<white;i++)
     {
        if(matx[x[i].index]==-1)
        {
           memset(used,0,sizeof(used));
           if(find(x[i].index))   
           {
              match++;
              //cout<<x[i].index<<endl;
           }
        }
     }
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)   
    {
       cin>>p[i].pno;
       if(isPrime(p[i].pno))      p[i].isPrime=true;
       else                       p[i].isPrime=false;
    }
    for(int i=0;i<n;i++)   cin>>p[i].grade>>p[i].range;
    white=black=0;
    for(int i=0;i<n;i++)
    {
        if(p[i].isPrime)    p[i].cno=black++;
        else                
        {
            p[i].cno=white;
            x[white].index=white;
            x[white++].grade=p[i].grade;
        }
    }
    memset(adjl,0,sizeof(adjl));
    for(int i=0;i<n;i++)
    {
        if(!p[i].isPrime)
        {
            for(int j=max(0,i-p[i].range);j<=min(i+p[i].range,n-1);j++)
            {
                if(p[j].isPrime)
                {
                   int r=++adjl[p[i].cno][0];
                   adjl[p[i].cno][r]=p[j].cno;
                }
            }
        }
    }
    /*for(int i=0;i<white;i++)
    {
        cout<<i<<":  ";
        for(int j=1;j<=adjl[i][0];j++)
        {
           cout<<adjl[i][j]<<" ";
        }
        cout<<endl;
    }*/
    sort(x,x+white,cmp);
    memset(matx,-1,sizeof(matx));
    memset(maty,-1,sizeof(maty));
    match=0;
    hungary();
    int sum=0;
    for(int i=0;i<n;i++)
    {
        if(!p[i].isPrime)
        {
            if(matx[p[i].cno]!=-1)    sum+=p[i].grade;
        }
    }
    cout<<match<<endl;
    cout<<sum<<endl;
    //system("pause");
    return 0;
}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics