D - Winning an Auction

本文深入探讨了一款拍卖游戏的最优策略求解方法,通过动态规划算法,计算Alice和Bob在给定初始资金和轮数的情况下,如何获取尽可能多的物品。文章提供了详细的代码实现,展示了如何利用博弈论和DP技巧解决复杂问题。
摘要由CSDN通过智能技术生成

链接:https://vjudge.net/contest/333183#problem/D

Alice and Bob play an auction game. Alice has A dollars and Bob has B dollars initially. There are N items on sale. In each round, an item will be sold by the following way. Alice writes down an integer a (0 ≤ a ≤ A) and Bob writes down an integer b (0 ≤ b ≤ B), which are the amount of dollars they want to pay for the item. If a > b, then Alice gets the item and pays a dollars to the seller. If a < b, then Bob gets the item and pays b dollars to the seller. If a = b, then for the 1st, 3rd, 5th, 7th ... round, Alice gets the item and pays a dollars; for the 2rd, 4th, 6th, 8th ... round, Bob gets the item and pays b dollars. Since all the items have the same value, the goal of the auction game is to get as many items as possible. Both Alice and Bob know the values of N,A and B. Your task is to calculate how many items they will get if both of them play optimally. 

Input

The first line is the number of test cases. Each test case contains 3 integers N,A and B, which are no larger than 255.

Output

For each test case, output the number of items Alice and Bob will get if both of them play optimally.

Sample Input

3
1 1 2
2 4 2
3 3 3

Sample Output

Alice 0 Bob 1
Alice 1 Bob 1
Alice 2 Bob 1

思路:

作为一名蒟蒻,看着题解也写出tle,QAQ,后来还好有老瞎眼学长独具慧眼看出了我tle的原因。首先这道题是一道看似博弈的dp,也就是博弈dp,我们无法得知每次拍卖时对方拍卖的价格,所以对于A或B来说,他可能使用任意的钱来拍卖当前拍品,但我们可以得知对方还剩余多少钱(似乎没什么用QAQ)

题解:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
typedef long long ll;
using namespace std;
int dp[256][256][256];
int f(int n,int a)
{
    int t=n/2;
    return t*a+(n-t)*(a+1);
}
int main()
{ 
    for(int i=0;i<256;i++)
    {
	    for(int j=0;j<256;j++)
	     {
	    	if(i>=j) 
			dp[1][i][j]=1;
	   		else 
			dp[1][i][j]=0;
	     }
    }
    for(int i=2;i<256;i++)
    {
	    for(int a=0;a<256;a++)
	     {
	        int t=min(f(i,a),256);
	        for(int b=0;b<t;b++)
	        {
	            if(a==b)
				{
					dp[i][a][b]=(i+1)/2; 
					continue;
				}  
	            int ta=i-dp[i-1][b][a];
	            int tb=0;
	            int j=1;
	            while(1)
	            {
					tb=i-1-dp[i-1][b-j][a];
	                if(b<j||tb>=ta) 
	                {
	                    dp[i][a][b]=ta;
	                    break;
	                }	
					ta=i-dp[i-1][b][a-j];
	                if(a<j||ta<=tb)  
	                {
	                    dp[i][a][b]=tb;
	                    break;
	                }
	                j++; 
	            }
	        }
    	}
    }       
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,a,b;
        scanf("%d%d%d",&n,&a,&b);
        printf("Alice %d Bob %d\n",dp[n][a][b],n-dp[n][a][b]);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值