UVALive 5760 Alice and Bob(博弈+記憶化dp or 找規律)

題意:

黑板上寫了n(n<=50)個不超過1000的數,
雙方輪流進行以下操作中的一種:

  • 將一個數減1,當某個數爲0時將其擦去;
  • 將兩個數擦去,並將兩個數之和寫上黑板;

擦去最後一個數爲勝者,Alice先手,求最後勝者。

思路:

如果所有數都是大於1的數,共可執行 cnt 次操作,其中:

cnt=sum(a[i])+n1

當 cnt 爲奇數時先手勝利,偶數時後手勝利。
如果有的數爲1,把1與其他數合併,操作數-1;把1直接-1,操作數-2.於是我們可以根據這個轉移規則來進行dp。
dp[i][j] = 1的個數爲i,其他>1的數可操作次數爲j時的勝負情況。

當然了,找規律也可以。

代碼:

//記憶化dp
#include<bits/stdc++.h>
using namespace std;

int n ;
const string win[2] = { "Bob", "Alice" } ;
int dp[55][50005] ;
bool dfs( int n , int m )
{
    if ( dp[n][m] != -1 ) return dp[n][m] ;
    int &res = dp[n][m] = 0 ;
    if ( !n ) return res = ( m & 1 );
    if ( !m ) return res = ( n % 3 != 0 ) ;
    if ( n == 1 ) return res = 1 ;
    if ( m == 1 ) return res = dfs( n + 1 , 0 ) ;
    if ( !dfs( n - 1 , m ) ) res = 1 ;
    if ( m > 1 && !dfs( n - 1 , m + 1 ) ) res = 1 ;
    if ( m > 1 && !dfs( n , m - 1 ) ) res = 1 ;
    if ( n > 1 && !dfs( n - 2 , m? m + 3 : m + 2 ) ) res = 1 ;
    return res ;
}
int main()
{
    int t ; cin >> t ; int kase = 1 ;
    memset( dp , -1 , sizeof dp ) ;
    while ( t-- ) {
        scanf( "%d" , &n ) ;
        int one = 0 , more = 0 ;
        for ( int i = 0 ; i < n ; i++ ) {
            int tmp ; scanf( "%d" ,&tmp ) ;
            if ( tmp == 1 ) one++ ;
            else more += tmp ;
        }
        if ( one != n ) more += n - one - 1 ;
        bool ok = dfs( one , more ) ;
        printf( "Case #%d: " , kase++ ) ;
        cout << win[ok] << endl ;
    }
    return 0;
}
//找規律
#include<bits/stdc++.h>
using namespace std;

const string win[2] = { "Bob", "Alice" } ;
int n ;
bool check( int cnt , int sum )
{
    if ( sum == cnt || sum == cnt + 2 ) {
        if ( cnt % 3 == 0 ) return 0 ;
        else ;
    } else {
        sum += ( n - 1 ) ;
        if ( sum % 2 == 0 && cnt % 2 == 0 ) return 0 ;
    }
    return 1 ;
}
int main()
{
    int t ; cin >> t ; int kase = 1 ;
    while ( t-- ) {
        scanf( "%d" , &n ) ;
        int one = 0 , sum = 0 ;
        for ( int i = 0 ; i < n ; i++ ) {
            int tmp ; scanf( "%d" ,&tmp ) ;
            if ( tmp == 1 ) one++ ;
            sum += tmp ;
        }
        bool ok = check( one , sum ) ;
        printf( "Case #%d: " , kase++ ) ;
        cout << win[ok] << endl ;
    }
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章