昆特牌 解题报告

昆特牌

题目背景

什么?你还有一场 NOIP 模拟赛? 什么都别说,先来盘昆特牌吧!

题目描述

昆特牌是一款双人对战卡牌游戏,游戏规则现简化如下:

游戏简化为仅有一局;

每位牌手有三行,分别是近战、远程和攻城;

每位牌手每次按顺序出一张牌;

每位牌手有同样数量张牌,而聪明的你能预知对手每次出的牌!

牌分为以下几种功能:

  • 单位牌:有一个点数和放置位置,\(0\)\(1\)\(2\)分别表示近战、远程和攻城,放置在你的场上;
  • 天气牌:有一个影响位置\(0\)\(1\)\(2\)分别表示近战、远程和攻城, 对你的和对手的相应行都会影响。天气下的单位无法被烧灼(烧灼下面有解释),天气下的单位计算点数和的时候视为每个为\(1\),对已经有天气牌的行使用视作无效;
  • 反天气牌:去除所有的天气牌并去除天气牌的视为每个为\(1\)效果(当然也包括其他效果);
  • 烧灼牌:消灭全场现有战力最高的单位(包括自己的单位)(除了天气下的), 若有多个则都消灭,若没有单位则视为无效,后续放入同行的单位仍然视作被天气影响;
  • 号角牌:选择\(6\)行(包括对手的)中一行使该行现有单位战力翻倍,但不能对天气牌影响下的行使用。如果每行都有天气视作无效,否则必须选择一行。由于丢了一些牌,这种卡最多只会出现 2 张,而且只有你有。这种牌视为立刻生效,然后消失;

所有牌都必须使用,且除了单位牌其他牌都没有点数。视作无效的牌不影响整个出牌过程,打出它什么用都没有,但你还是打出了它。

你想要让最后你的点数和减去对手的尽量大(不是绝对值!),该怎么办呢?

输入输出格式

输入格式

第一行两个数\(W,N\)分别表示先后手和每人牌数,\(W=0\)表示你先手,\(W=1\)表示对手先。

接下来依次\(N\)行表示对手每次出的牌:

  • \(t=1\),这是一张单位牌,接下来\(x,y\)分别表示战力和位置;
  • \(t=2\),这是一张天气牌,接下来\(x\)表示位置;
  • \(t=3\),这是一张反天气牌;
  • \(t=4\),这是一张烧灼牌;
  • \(t=5\),这是一张号角牌。

接下来\(N\)行表示你的牌,描述同上。

输出格式

点数和差的最大值和点数和差最大方案数,用空格分隔。

号角放在不同行算不同方案(无效不算放在一行,但也是一种方案,同 012 行不同),且每张牌是不同的

例如你有两种方案:第一张号角放在你的 1 行第二张号角放在你的 0 行与第一张号角放在你的 0 行第二张号角放在你的 1 行不同。

数据范围

对于\(10\%\)的数据,\(t\in\{1\}\)

对于\(20\%\)的数据,\(t\in\{1,2\}\)

对于\(40\%\)的数据,\(t\in\{1,2,3\}\)

对于\(60\%\)的数据,\(t\in\{1,2,3,4\}\)

对于\(100\%\)的数据,\(N\le 7,1\le\)所有单位战力\(\le 1000\)

TIPS

好好读题!

好好读题!

好好读题!


要是联赛来这么一道大模拟我就飞了(flag

首先读错题了,以为自己出牌的顺序也是给定好了。其次回溯时没想好怎么存原来的状态瞎搞了。

以后做这种题一定要先想好,把题目读清楚,把大致思路理清楚,对怎么写大致有个结构认识再动笔

也算是提醒了我自己,搜索时的状态如果理不太清楚直接开另外一个东西把状态存下来,待会再还回去。反正系统栈不差你这点东西。


思路(流程):

  1. \(\tt{next\_permutation()}\)直接搞自己出牌的全排列
  2. 搜索自己和敌方出牌
    • \(\tt{vector}\)存每个人每一行的战斗力
    • 加人时\(\tt{tmp}\)存一下一行的,搜完了还回去
    • 天气一样,存一下
    • 砍最大值可以先存下来,然后\(\tt{sort}\)先找到,再去删掉

学习了一些有关\(\tt{vector}\)的姿势

vector <int> a;
a.pop_back();
a.front();
a.back();

Code:

#include <cstdio>
#include <vector>
#include <algorithm>
std::vector <int > dw[2][3];
struct node
{
    int id,op,x,y;
    bool friend operator <(node n1,node n2){return n1.id<n2.id;}
}opt[2][10];
int weather[3],n,w;
int cal()
{
    int c[2]={0,0};
    for(int i=0;i<=2;i++)
        for(int k=0;k<=1;k++)
        {
            if(weather[i])
                c[k]+=dw[k][i].size();
            else
                for(int p=0;p<dw[k][i].size();p++)
                    c[k]+=dw[k][i][p];
        }
    return c[0]-c[1];
}
int max(int x,int y){return x>y?x:y;}
int mxa=-0x3f3f3f3f,ans;
void dfs(int who,int dep)
{
    if(dep==n+1)
    {
        int d=cal();
        if(mxa<d) mxa=d,ans=1;
        else if(mxa==d) ++ans;
        return;
    }
    if(opt[who][dep].op==1)
    {
        int x=opt[who][dep].x,y=opt[who][dep].y;
        std::vector <int > tmp=dw[who][y];
        dw[who][y].push_back(x);
        dfs(who^1,dep+(who!=w));
        dw[who][y]=tmp;
    }
    else if(opt[who][dep].op==2)
    {
        int x=opt[who][dep].x;
        int tmp=weather[x];
        weather[x]=1;
        dfs(who^1,dep+(who!=w));
        weather[x]=tmp;
    }
    else if(opt[who][dep].op==3)
    {
        int tmp[3];
        for(int i=0;i<=2;i++) tmp[i]=weather[i],weather[i]=0;
        dfs(who^1,dep+(who!=w));
        for(int i=0;i<=2;i++) weather[i]=tmp[i];
    }
    else if(opt[who][dep].op==4)
    {
        int mx=0;
        std::vector <int> tmp[2][3];
        for(int i=0;i<=2;i++)
        {
            if(!weather[i])
            {
                for(int k=0;k<=1;k++)
                {
                    tmp[k][i]=dw[k][i];
                    std::sort(dw[k][i].begin(),dw[k][i].end());
                    if(!dw[k][i].empty()) mx=max(mx,dw[k][i].back());
                }
            }
        }
        for(int i=0;i<=2;i++)
            if(!weather[i])
                for(int k=0;k<=1;k++)
                    while(!dw[k][i].empty()&&dw[k][i].back()==mx) dw[k][i].pop_back();
        dfs(who^1,dep+(who!=w));
        for(int i=0;i<=2;i++)
            if(!weather[i])
                for(int k=0;k<=1;k++)
                    dw[k][i]=tmp[k][i];
    }
    else
    {
        for(int i=0;i<=2;i++)
        {
            if(!weather[i])
                for(int k=0;k<=1;k++)
                {
                    for(int p=0;p<dw[k][i].size();p++)
                        dw[k][i][p]*=2;
                    dfs(who^1,dep+(who!=w));
                    for(int p=0;p<dw[k][i].size();p++)
                        dw[k][i][p]/=2;
                }
        }
        if(weather[0]&weather[1]&weather[2]) dfs(who^1,dep+(who!=w));
    }
}
int main()
{
    scanf("%d%d",&w,&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&opt[1][i].op);
        if(opt[1][i].op==1)
            scanf("%d%d",&opt[1][i].x,&opt[1][i].y);
        if(opt[1][i].op==2)
            scanf("%d",&opt[1][i].x);
    }
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&opt[0][i].op);
        if(opt[0][i].op==1)
            scanf("%d%d",&opt[0][i].x,&opt[0][i].y);
        if(opt[0][i].op==2)
            scanf("%d",&opt[0][i].x);
        opt[0][i].id=i;
    }
    dfs(w,1);
    while(std::next_permutation(opt[0]+1,opt[0]+1+n))
        dfs(w,1);
    printf("%d %d\n",mxa,ans);
    return 0;
}

2018.11.6

posted @ 2018-11-06 14:30  露迭月  阅读(425)  评论(0编辑  收藏  举报