您的位置:首页 > 其它

UVALive 6462 状压DP

2015-10-26 20:51 465 查看
UVALive 6462

题目链接:

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4473

题意:

两个人轮流选包,包里有一些颜色。包选完后放到柜子里。

规定柜子里如果某种颜色的个数大于等于S个时,柜子里该颜色的个数减S,此轮该人得到一颗魔法石。该操作在每轮会自动进行到不能进行为止。得到魔法石后下一轮仍然由此人执行。

两人都拥有最优策略。

问先手的人减后手的人的魔法石数。

思路:

简单状压。

模拟的时候使劲T,原因是多加了一维状态dp[i][j],j = 0,1表示是Alice还是Bob,去掉就A了。

源码:

include

include

include

include

include

include

include

include

using namespace std;

define inf (1000000007)

int dp[1<<21];

int col[1<<21][11];

int cnt[100];

int data[100][100];

int G, B, S;

void dfs(int s, int p)

{

if(dp[s] != -inf) return;

if(s == ((1 << B) - 1)){

dp[s] = 0;

return;

}

for(int k = 0 ; k < B ; k++){

if((s & (1 << k)) == 0){

int ts = s | (1 << k);

for(int l = 0 ; l <= G ; l++)

col[ts][l] = col[s][l];

int val = 0;

for(int l = 1 ; l <= G ; l++){

col[ts][l] += data[k][l];

if(col[ts][l] >= S){

val++;

col[ts][l] %= S;

}

}

// printf(“i = %d, j = %d, val = %d, ts = %d, dp = %d\n”, i, j, val, ts, dp[i][j]);

if(val == 0){

dfs(ts, !p);

dp[s] = max(dp[s], -dp[ts]);

}

else{

dfs(ts, p);

dp[s] = max(dp[s], val + dp[ts]);

}

}

}

}

int main()

{

// freopen(“I.in”, “r”, stdin);

while(scanf(“%d%d%d”, &G, &B, &S) != EOF && G + B + S){

if(B == 0){

printf(“%d\n”, 0);

continue;

}

int sum = 0;

memset(data, 0, sizeof(data));

for(int i = 0 ; i < B ; i++){

scanf(“%d”, &cnt[i]);

sum += cnt[i];

int u;

for(int j = 0 ; j < cnt[i] ; j++) scanf(“%d”, &u), data[i][u]++;

}

for(int i = 0 ; i < (1 << B) ; i++)

dp[i] = -inf;

memset(col, 0, sizeof(col));

dfs(0, 0);

// for(int i = 0 ; i < (1 << B) ; i++)

// for(int j = 0 ; j < 2 ; j++)

// printf(“dp[%d][%d] = %d\n”, i, j, dp[i][j]);

// for(int i = 0 ; i < (1 << B) ; i++){

// printf(“color “);

// for(int j = 1 ; j <= G ; j++)

// printf(“%d “, col[i][j]);

// printf(“\n”);

// }

int ans = dp[0];

// if(dp[(1<
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: