HDU 5811 Colosseo

来源:互联网 发布:上海烟草网络销售网 编辑:程序博客网 时间:2024/06/02 02:45

转载声明:http://blog.csdn.net/ShinFeb/article/details/52165853
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5811

复习注意点: 注意贪心强弱关系,不能顺其自然的想.

题意:
给你N只怪兽,然后每一只都会互相打,一个”叫兽”,会将这堆怪兽分成两堆,T1,T2.如果分出来的2堆都存在一个序列(A1….Am)其中 (Ai stronger than Aj)(1<=i < j < = m),那么尝试着从T2拿k只怪兽到T1,输出最大的k只.

个人感想:
首先看到题目的时候我就感觉并不太难,然后我很快就写完了代码,但是我发现我的代码只能过小数据,并不能过大数,,orz,我完全不知道什么原因,我想了很久,我以为我看错题了,我就是想不出为什么.然后看了网上的题解,我也不明白是什么回事,.代码实在不是我这种蒟蒻能够看得懂,我一点点转换到我的代码中,我才发现我和大牛的代码其实就差在了LIS中.我是太不细心了..我又自然而然的以为了.

首先
给你一堆T1的所有怪兽,然后我们整理出T2的怪兽,通过关系表,我们先从 弱->强 排列然后逐一判断弱的怪兽是不是比后面的怪兽都弱.
我们用 <来表示弱强关系.
T1:a1 < b1 < c1 < d1….z1
T2:a2 < b2 < c2 < d2…z2
我尼玛的突然很自然地想从a2开始尝试的放进去,如果满足这里的强弱关系,就放.因为b2如果也满足,那么肯定也满足a2 < b2..但这样想必然错,为什么?
这里写图片描述

可以通过图观察到,b2能打败b1,a1。 a2能打败a1,b1,c1,d1 但是b2明显是比a2强,这样选择是不合法的,,所以就为什么会有最长上升子序列的出现,为的就是尽量满足T1串的格局

网上都说这题卡常数,要改输入读才行,,我的复杂度是o(2(nlogn+n^2)) 也不让过..我也不知道该怎么改了..

我改了输入外挂也过不去,尼玛在我的本机才跑0.4s,这也不能过..什么鬼.
这里写图片描述

我尼玛我改了几次了这博客,,心有不甘,连输出外挂也得改了才能过..

AC代码..

/* Author:GavinjouElephant * Title: * Number: * main meanning: * * * */#include <iostream>using namespace std;#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>#include <sstream>#include <cctype>#include <vector>#include <set>#include <cstdlib>#include <map>#include <queue>//#include<initializer_list>//#include <windows.h>//#include <fstream>//#include <conio.h>#define MaxN 0x7fffffff#define MinN -0x7fffffff#define Clear(x) memset(x,0,sizeof(x))const int INF = 0x3f3f3f3f;typedef long long ll;const int maxn = 1005;int G[maxn][maxn];int n, m;int root;int org[maxn];int org2[maxn];bool vis[maxn];int  q[maxn];int  b[maxn];int k ;int Scan(){    int res = 0, ch, flag = 0;    if((ch = getchar()) == '-')             //判断正负        flag = 1;    else if(ch >= '0' && ch <= '9')           //得到完整的数        res = ch - '0';    while((ch = getchar()) >= '0' && ch <= '9' )        res = res * 10 + ch - '0';    return flag ? -res : res;} void Out(int a)    //输出外挂 {     if(a>9)         Out(a/10);     putchar(a%10+'0'); }bool cmp(const int a, const int b){    return !G[a][b];}int top;int top2;bool judge(){    for(int i = 0; i < top; i++)    {        for(int j = i + 1; j < top; j++)        {            if(G[org[i]][org[j]])return false;        }    }    for(int i = 0; i < top2; i++)    {        for(int j = i + 1; j < top2; j++)        {            if(G[org2[i]][org2[j]])return false;        }    }    return true;}void solve(){    int j;    for(int i = 0; i < top2; i++)    {        for(j = 0; j < top; j++)        {            if(G[org2[i]][org[j]])continue;            else break;        }        q[i] = j;        for(;j <top; j++)        {            if(G[org2[i]][org[j]])            {                q[i] = -1;                break;            }        }    }    //最长上升子序列    int tot = 0;    for(int i = 0; i <top2; i++)    {        if(q[i] == -1)continue;        if(!tot || q[i] >= b[tot])b[++tot] = q[i];        else  *upper_bound(b + 1, b + tot + 1, q[i]) = q[i];    }    printf("YES ");    Out(tot);    printf("\n");}int main(){    while(scanf("%d%d", &n, &m), n + m)    {        memset(vis, false, sizeof(vis));        top = m;        top2 = 0;        for(int i = 1; i <= n; i++)        {            for(int j = 1; j <= n; j++)            {               G[i][j]=Scan();            }        }        for(int i = 0; i < m; i++)        {            scanf("%d", &org[i]);            vis[org[i]] = true;        }        for(int i = 1; i <= n; i++)        {            if(!vis[i])            {                org2[top2++] = i;            }        }        sort(org, org + top, cmp);        sort(org2, org2 + top2, cmp);        if(!judge())        {            printf("NO\n");            continue;        }        solve();    }    return 0;}
0 0