codeforces 1089A.lice the Fan(记忆化搜索dp)

题解:主要在于第五局的时候比赛次数不一样了,所以多开一维专门代表时候打满了5场。

dp[0]代表没打满五场,1代表打满了5场] [胜了wa场] [败了wb场] [共赢了na个球] [共输了nb个球]。

#include"bits/stdc++.h"
using namespace std;
const int MX = 202;
int dp[2][5][5][MX][MX];
struct node
{
    int a,b;
    node() {}
    node(int a, int b): a(a), b(b) {}
};
vector<node> g[2][5][5][MX][MX];
void update(int lim,int wa, int wb, int a, int b, int ta, int tb)
{
    dp[1][wa][wb][a][b] = 1;
    g[1][wa][wb][a][b].push_back(node(ta,tb));
}
void get_ans(int l1,int wa1, int wb1, int a1, int b1, int l2,int wa2, int wb2, int a2, int b2, int ta, int tb)
{
    dp[l1][wa1][wb1][a1][b1] = 1;
    g[l1][wa1][wb1][a1][b1].push_back(node(ta,tb));
    for(int i = 0; i < g[l2][wa2][wb2][a2][b2].size(); i++)
        g[l1][wa1][wb1][a1][b1].push_back(g[l2][wa2][wb2][a2][b2][i]);
}
bool dfs(int a, int b, int wa, int wb, int na, int nb, int dep, bool lim, bool w)
{
    if(dp[lim][wa][wb][na][nb] >= 0) return dp[lim][wa][wb][na][nb];
    if(lim&&dep==5)
    {
        if(wa && ((na > 15 && na-nb == 2) || (na == 15 && nb <= 13)) )
        {
            update(1,wa,wb,na,nb,na,nb);
            return 1;
        }
        if(wb && ((nb > 15 && nb-na == 2) || (nb == 15 && na <= 13)) )
        {
            update(1,wa,wb,na,nb,na,nb);
            return 1;
        }
        return dp[1][wa][wb][na][nb] = 0;
    }

    if(wa && na >= 25 &&(!w || (w && wb == 0)) )
        for(int tb  = 0; tb <= min(nb,na-2); tb++)
        {
            int ta = 25;
            if(tb > 23)ta += tb-23;
            if(dfs(a,b,wa-1,wb,na-ta,nb-tb,dep+1,lim,w))
            {
                get_ans(lim,wa,wb,na,nb,lim,wa-1,wb,na-ta,nb-tb,ta,tb);
                return 1;
            }
        }
    if(wb && nb >= 25 &&(w || (!w && wa == 0)))
        for(int ta = 0; ta <= min(na,nb-2); ta++)
        {
            int tb = 25;
            if(ta > 23) tb += ta-23;
            if(dfs(a,b,wa,wb-1,na-ta,nb-tb,dep+1,lim,w))
            {
                get_ans(lim,wa,wb,na,nb,lim,wa,wb-1,na-ta,nb-tb,ta,tb);
                return 1;
            }
        }
    return dp[lim][wa][wb][na][nb] = 0;
}


void init()
{
    memset(dp,-1,sizeof(dp));
    int n = 200;
    for(int i = 0; i <= n; i++)
        for(int j = 0; j <= n; j++)
            dp[0][0][0][i][j] = dp[1][0][0][i][j] = 0;
    dp[0][0][0][0][0] = dp[1][0][0][0][0] = 1;
    for(int i = 0; i <= n; i++)
    {
        for(int j = 0; j <= n; j++)
        {
            if(dfs(i,j,3,0,i,j,1,0,1)) continue;
            if(dfs(i,j,3,1,i,j,1,0,1)) continue;
            if(dfs(i,j,3,2,i,j,1,1,1)) continue;
            if(dfs(i,j,2,3,i,j,1,1,0)) continue;
            if(dfs(i,j,1,3,i,j,1,0,0)) continue;
            if(dfs(i,j,0,3,i,j,1,0,0)) continue;
        }
    }
}

void print(int t,int wa, int wb,int a, int b)
{
    printf("%d:%d\n",wa,wb);
    for(int i = 0; i < g[t][wa][wb][a][b].size(); i++)
    {
        printf("%d:%d%c",g[t][wa][wb][a][b][i].a,g[t][wa][wb][a][b][i].b," \n"[i+1==g[t][wa][wb][a][b].size()]);
    }
}
int main()
{
#ifdef LOCAL
    freopen("input.txt","r",stdin);
#endif // LOCAL
    int n;
    scanf("%d",&n);
    init();
    int a,b;
    for(int i = 1; i <= n; i++)
    {
        scanf("%d%d",&a,&b);
        if(dp[0][3][0][a][b] > 0) print(0,3,0,a,b);
        else if(dp[0][3][1][a][b] > 0) print(0,3,1,a,b);
        else if(dp[1][3][2][a][b] > 0) print(1,3,2,a,b);
        else if(dp[1][2][3][a][b] > 0) print(1,2,3,a,b);
        else if(dp[0][1][3][a][b] > 0) print(0,1,3,a,b);
        else if(dp[0][0][3][a][b] > 0) print(0,0,3,a,b);
        else puts("Impossible");
    }
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值