http://acm.hdu.edu.cn/showproblem.php?pid=4317
Test instructions
There are n heap of stones, each pile of stones have a certain number of stones, now you can add any number of stones in the heap, so that the initiator will be defeated.
Ideas:
The first thing we can find is that, according to the knowledge of the Nim game, we know that n heap of stones will be defeated in the condition that the stone number of n heap or value of 0, then the problem is transformed into n heap of stones added a certain number of stones, so that the final difference or value into 0. Because XOR or a per-bit operation, so we consider a bitwise, for the n number of one, its value depends on the previous (i-1) on its carry and the value of its own, so when we meet the bit I, one of the factors to consider is the i-1 of the rounding, We use a status J to represent the situation, so that the end result of the I bit should be the value of itself and then the value of the carry-over, plus the additional value is the final value. Here we can think of the state compression DP, with F (i,j) to indicate that the first I bit has become 0, and the first bit to the i+1 position of the status of J is the minimum number of stones required to add. State transitions are, of course, i-1, so it is also necessary to enumerate the i-1 as a carry k to the I-bit, and then use the bitwise operation to solve the problem.
The specific implementation process is this:
The resulting carry condition is: TMP = num[i] & k
The value after rounding is: y = num[i] ^ k;
Determine if the resulting carry is legitimate: J & tmp = = tmp?
How many bits of rounding are needed: x = j ^ tmp
The cost of rounding: t[x & y] * D[i] + t[x^y&x] * 2 * d[i];
The new state after rounding is: now = y & (~x)
Code:
#include <stdio.h> #include <string.h> const int BB = 21;
int N;
int T[1<<BB];
int d[bb+1];
int NUM[BB];
int VAL[BB];
int maxbit;
int dp[bb][1<<10];
void Init () {d[1] = 1;
for (int i=2;i<=bb;i++) d[i] = d[i-1]<<1; for (int i=0;i< (1<<BB); i++) {int tmp = i;
T[i] = 0;
while (TMP) {if (tmp&1) t[i] + +;
TMP >>= 1;
}}} int MIN (int a, int b) {if (a = =-1) return B; else return a < b?
A:B;
} void Solve () {memset (DP,-1, sizeof (DP));
Dp[0][0] = 0;
int MM = 1 << N;
for (int i=1;i<=maxbit;i++) {for (int j=0;j<mm;j++) {if (dp[i-1][j] = =-1) continue;
int tmp = Num[i] & j;
int v = num[i] ^ j;
for (int k=tmp;k<mm;k++) {if ((k&tmp) = = tmp) {int x = k ^ tmp; int add = t[x & V]*d[i] + t[(X^V) &x] * 2 * d[i];
int now = v & (~x);
if ((t[now]&1) ==0) {Dp[i][k] = MIN (Dp[i][k], dp[i-1][j] + add); } else if (T[now]! = N) {Dp[i][k] = MIN (Dp[i][k], Dp[i-1][j] + add + d[i])
;
}}}}} int ans =-1;
for (int j=0;j<mm;j++) {if (Dp[maxbit][j]==-1 | | t[j]%2==1) continue;
Ans = MIN (ans, dp[maxbit][j]);
} if (ans = =-1) printf ("impossible\n");
else printf ("%d\n", ans);
} int main () {init ();
while (scanf ("%d", &n) = = 1) {maxbit = 0;
for (int i=1;i<=n;i++) {scanf ("%d", &val[i]);
int tmp = Val[i];
int c = 0;
while (TMP) {C + +;
TMP >>=1;
} if (Maxbit < c) Maxbit = C; } for (int i=1;i<=maxbit;i++) {Num[i] = 0;
for (int j=1;j<=n;j++) {if (Val[j]&d[i]) num[i] + = d[j];
}} solve ();
} return 0;
}