XinanTanOJ 1168 Alice and Bob 二维DP

Alice and Bob

Accepted : 58   Submit : 185
Time Limit : 1000 MS   Memory Limit : 65536 KB

Problem Description

Alice and Bob always love to play games, so does this time. 
It is their favorite stone-taken game. 
However, this time they does not compete but co-operate to finish this task. 
Suppose there is a stack of n stones. 
Each turn, 
Alice can only take away stones in number pow of 2, say 1, 2, 4, 8, 16, ... 
Bob can only take away stones in number pow of 3, say 1, 3, 9, 27, 81, ... 
They takes stones alternately, and lady first.
Notice in each turn, Alice/Bob have to take away at least one stone, unless the stack is empty. 
Now, the question is, what is the least number of operation for taking away all the stones.

Input

Multiple test cases. First line, there is an integer T ( 1 ≤ T ≤ 20 ), indicating the number of test cases. 
For each test case, there is a number n ( 1 ≤ n ≤ 10000 ), occupying a line, indicating the total number of the stones.

Ouput

For each test case, output a line. It is an integer number k, indicating the least number of operation in need to finish the task.

Sample Input

5
1
2
3
4
5

Sample Output

1
1
2
1
2

Source

XTU OnlineJudge

这是今年湘潭赛的一道题,我记得我当时是用暴力过的。。。。。
完全没有dp的思想,这次回头看了一下这道题,对这道题目的印象很深刻
题意是alice和bob联合一起取石块,alice先bob后,alice只能去2的n次方,bob只能取3的n次方的石子,看两人合作 最少去几次能把石子全部取完
开始使用一维dp做的,后来发现求n时并不是(a[n-i] 和a[i]之和的最小值) ,不能全部表示所有的状态
看了解题报告,这个应该用二维dp,然a[i][0] 是代表i个石子,轮到aclie取得最小步数,a[i][1]是代表i个石子,轮到bob取的最小步数
这样两个dp就出来结果了
a[i][0]=min(a[i-2^k][1])+1) 代表 alice 取一次,后得到的 bob取得最小数量加上刚才aclice取得1次,等于alice取得最小次数
a[i][1]=min(a[i-3^k][0]+1)

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
int Min(int a,int b){
   if(a>b)return b;
   else return a;    
}
int a[11000][2];
void fun(){
    a[0][0]=0;a[0][1]=0;a[1][0]=1;a[1][1]=1;a[2][0]=1;a[2][1]=2;
    for(int i=3;i<=10000;i++){
       a[i][0]=11000;
       a[i][1]=11000;
       for(int j=1;j<=i;j=j*2){
           a[i][0]=min(a[i][0],a[i-j][1]+1);        
       } 
       for(int j=1;j<=i;j=j*3){
           a[i][1]=min(a[i][1],a[i-j][0]+1);        
       }
    }     
     
}
int main()
{
    int n;
    scanf("%d",&n);
    fun();
    while(n--){
        int num;
        scanf("%d",&num);
        printf("%d\n",a[num][0]);           
               
    }

    return 0;
} 






你可能感兴趣的:(算法)