• Codeforces Gym 100015F Fighting for Triangles 状压DP


    Fighting for Triangles

    题目连接:

    http://codeforces.com/gym/100015/attachments

    Description

    Andy and Ralph are playing a two-player game on a triangular board that looks like the following:

    1 2
    3
    4 5 7 8
    6 9
    10 11 13 14 16 17
    12 15 18

    At each turn, a player must choose two adjacent vertices and draw a line segment that connects them.
    If the newly drawn edge results in a triangle on the board (only the smallest ones count), then the player
    claims the triangle and draws another edge. Otherwise, the turn ends and the other player plays. The
    objective of the game is to claim as many triangles as possible. For example, assume that it is Andy’s turn,
    where the board has fives edges as shown in the picture below. If Andy draws edge 6, then he will claim the
    triangle formed by edge 4, 5, and 6, and continue playing.

    Given a board that already has some edges drawn on it, decide the winner of the game assuming that
    both Andy and Ralph play optimally. Andy always goes first. Note that if a triangle exists on the board
    before the first move, neither player claims it.

    Input

    The input consists of multiple test cases. Each test case begins with a line containing an integer N,5 !
    N ! 10, which indicates the number of edges that are already present on the board before the game begins.
    The next line contains N integers, indicating the indices of these edges. The input terminates with a line
    with N = 0. For example:

    Output

    For each test case, print out a single line that contains the result of the game. If Andy wins, then print out
    “Andy wins”. If Ralph wins, then print out “Ralph wins”. If both players get the same number of triangles,
    then print out “Draw”. Quotation marks are used for clarity and should not be printed. For example, the
    correct output for the sample input above would be:

    Sample Input

    6

    1 2 3 4 5 6

    5

    4 5 6 7 8

    0

    Sample Output

    Andy wins

    Ralph wins

    Hint

    题意

    给你一个四层的三角形,一共有18条边

    然后A,B两个开始划线,如果当前人划线的时候,正好化成了一个小三角形,他就加一分,并且可以再画

    否则就该另外一个人画

    然后告诉你一些边已经被画过线了,问你先手是否能够胜利

    题解:

    直接暴力状压dp就好了

    dp[i]表示i这个状态的时候,A能够拿到的最多数

    注意trick,就是画线的时候,不仅仅可以占据一个三角形,有可能占据两个三角形哦

    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    int dp[1<<21][2];
    int Dis[1<<21][2];
    int cal(int x)
    {
        int vis[30];
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=18;i++)
            if((x>>i)&1)
                vis[i]=1;
        int ans = 0;
        for(int i=0;i<6;i++)
            if(vis[i*3+1]&&vis[i*3+2]&&vis[i*3+3])
                ans++;
        if(vis[3]&&vis[5]&&vis[7])ans++;
        if(vis[6]&&vis[11]&&vis[13])ans++;
        if(vis[9]&&vis[14]&&vis[16])ans++;
        return 9-ans;
    }
    int dfs(int now,int flag)
    {
        if(Dis[now][flag])return dp[now][flag];
        int last = cal(now);
        Dis[now][flag]=1;
        for(int i=1;i<=18;i++)
        {
            if(((now>>i)&1)==0)
            {
                int next = now|(1<<i);
                int flag3 = cal(now)-cal(next);
                if(flag3>0)
                    dp[now][flag]=max(dp[now][flag],dfs(next,flag)+flag3);
                else
                    dp[now][flag]=max(dp[now][flag],last-dfs(next,1-flag));
            }
        }
        return dp[now][flag];
    }
    
    int main()
    {
        //freopen("1.in","r",stdin);
        int n;
        while(cin>>n)
        {
            if(n==0)break;
            int now = 0;
            for(int i=0;i<n;i++)
            {
                int x;scanf("%d",&x);
                now|=(1<<x);
            }
            int last = cal(now);
            int a = dfs(now,0);
            int b = last - a;
            //cout<<last<<" "<<a<<" "<<b<<endl;
            if(a>b)
                cout<<"Andy wins"<<endl;
            else if(a==b)
                cout<<"Draw"<<endl;
            else if(a<b)
                cout<<"Ralph wins"<<endl;
        }
    }
  • 相关阅读:
    NND,优酷效果实在太差了
    技术人员创业的短板
    【上架通知】天轰穿.NET4趣味编程视频教程VS2010轻松学习C#零基础
    最新课程信息 课堂风格视频教程,中规中矩的教学思路设计和插诨打科的讲解方式
    Visual Studio 2010 Ultimate 中文旗舰版——提供下载地址和KEY
    整整半个月了
    学云网五一特惠活动,很喜感的图
    学员就业>我心纠结
    委托的定义和使用入门天轰穿
    第八 讲 : 流程控制循环语句 【天轰穿.Net4趣味编程系列视频教程vs2010轻松学习C#】
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5136004.html
Copyright © 2020-2023  润新知