2012 Multi-University Training Contest 2 [hdu4310~4319]

 

 

 

hdu4317 nim+狀壓dp, Unfair Nim 狀態很容易想到,轉移就噁心了。。。 不過屢清思路就好了

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cstdlib>
#include <cmath>
#include <stack>
#include <map>
#include <vector>
#include <string>
#include <algorithm>

const double pi=cos(-1.);
const double eps=10e-6;
const double eps1=10e-10;
const int inf=0x5fffffff;
const long long infl=1ll<<62;

///******macro defination******///
#define cas(a) int a; scanf("%d", &a); while (a--)
#define cas1(x, a) int a; scanf("%d", &a); for (int x=1; x<=a; ++x)
#define int(a) int a; scanf("%d", &a)
#define char(a) char a; scanf("%c", &a)
#define strr(a, x) char a[x]; scanf("%s", &a)
#define clean(a) memset (a, 0, sizeof(a));
#define up(x,a) for(int x=0; x<a; ++x)
#define down(x,a) for(int x=a-1; x>=0; --x)
#define up1(x,a) for (int x=1; x<=a; ++x)

#define debug(a) printf("here is %d!!!\n", a);
///*** mathmatics ***///
#define sqr(x) (x)*(x)
#define abs(x) (x)>0?(x):(-(x))
#define zero(x) (x)<eps && (x)>eps
///******   by Geners   ******///
typedef long long ll;
typedef unsigned int UI;

using namespace std;

int nim[50];
int row[50]; /// 記錄每位各個數的狀態
int dp[50][1024+123];/// dp[i][j] i位爲j進位時的最小值
/// dp[i][j]= min(dp[i-1][???] +bit(j)*(1<<i) , )  j&(~row) == 0
/// 如果當前位是0, 想進位 前狀態必須也有進位, 即1+10+1=100
///                 不進位 前狀態0 或1
/// 當前位是1, 進位 前狀態 0、1
///             不進位 前狀態0         轉移O(2^10 )總 O(20*2^20)

int getbit(int x)
{
    int res=0;
    while (x)
    {
        if(x&1)res++; x>>=1;
    }
    return res;
}

int main()
{
    int n;
    while (~scanf("%d", &n))
    {
        clean(row);
        int xsum=0;
        for (int i=0; i<n; ++i)
            scanf("%d", nim+i),xsum^=nim[i];
        for (int i=0; i<23; ++i)
        {
            for (int j=0; j<n; ++j)
            {
                if(nim[j]&(1<<i))row[i]|=(1<<j);
            }
            //if(row[i])printf("row[%d]=%d\n", i, row[i]);
        }
        int maxb=20;
        for (int j=25; j>=0; --j)
        {
            if(row[j]==0)continue;
            maxb=j+1; break;
        }
        //printf("xorsum=%d maxb=%d\n", xsum, maxb);
        int lim=1<<n;
        int mask=lim-1;
        for (int i=0; i<=maxb; ++i)
        {
            for (int j=0; j<lim; ++j)dp[i][j]=inf;
        }
        for (int i=0; i<=maxb; ++i)
        {
            for (int j=0; j<lim; ++j)
            {
                int bi=getbit(j);
                if(i==0)
                {
                    if((j&(~row[i]))==0)
                        if((bi+(xsum&(1<<i))&1)==0)
                        {
                            dp[i][j]=bi;
                            //printf("j==%d bi==%d %d\n", j, bi, row[i]);
                        }
                    else if((row[i]&mask)!=mask)dp[i][j]=bi+1;
                }
                else
                {
                    for (int k=0; k<lim; ++k)
                    {
                        if(dp[i-1][k]>=inf)continue;
                        //if(k==8 && i==1)printf(" %d %d\n", k|row[i], k & row[i]);
                        if( ( j & ( ~( k|row[i] ) ) )==0  && (~j & ( k & row[i] ))==0 )
                        {
                            if( ( ( bi - getbit(k^row[i]) - getbit(k&row[i]) ) & 1 ) )
                            {
                                if((mask&(k^row[i]))!=mask)
                                dp[i][j]=min(dp[i][j], dp[i-1][k]+(1<<i)*(bi-getbit(k&row[i])+1));
                            }
                            else
                            dp[i][j]=min(dp[i][j], dp[i-1][k]+(1<<i)*(bi-getbit(k&row[i])));

                            //printf("i==%d j==%d bi==%d k=%d  %d  dp=%d\n", i, j, bi, k, row[i], dp[i-1][k]+(1<<i)*(bi-getbit(k&row[i])));

                        }
                    }
                }
            }
        }
//        for (int i=0; i<=maxb; ++i)
//        {
//            for (int j=0; j<lim; ++j)
//            {
//                if(dp[i][j]<inf)printf("(%d, %d)=%d\n", i, j, dp[i][j]);
//            }
//        }
        int ans=inf;
        for (int i=0; i<lim; ++i)
        {
            if(~getbit(i)&1)
            ans=min(ans, dp[maxb][i]);
        }
        if(ans==inf)puts("impossible");
        else printf("%d\n", ans);
    }
    return 0;
}
/*
3
1 2 3
3
1 1 1
1
10
3
7 2 9
3
3 2 5
3
0 0 0
4
0 0 0 0
4
1 1 1 1
2
1000000 999999
5
35 9 7 48 28
4
1000000 999999 555 444
*/



 

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