UVa 10123 - No Tipping

来源:互联网 发布:淘宝双11红包怎么领 编辑:程序博客网 时间:2024/05/19 10:09

題目:在一個有兩個支點的槓桿上(支點在-1.5,+1.5),已知桿長和質量,以及上面的重物,

            問是否存在一個順序可以把所有的物品都拿下來,並且不打破平衡。

分析:狀態壓縮、記憶化搜索。數據較小,利用位表示選取狀態,每次兩個支點分別判斷平衡即可。

說明:注意開始時的平衡狀態,dp也可以╮(╯▽╰)╭。

#include <cstdio>#include <cstring>int states[1<<20], front[1<<20], space[20], weight[20];double balance(int n, int select, double support){double left = 0, right = 0;for (int i = 0; i < n; ++ i) if ((1<<i)&select) {if (space[i] < support) {left += weight[i]*(support-space[i]);}else {right += weight[i]*(space[i]-support);}}return left - right;}int test(int n, int select, double w){return (balance(n, select, -1.5)-w <= 0)&&(balance(n, select, 1.5)+w >= 0);}int save[20];int dfs(int n, int d, int state, double w){if (!states[state]) {states[state] = 1;}else {return 0;}if (!state) {for (int i = 0; i < n; ++ i)printf("%d %d\n",space[save[i]], weight[save[i]]);return 1;}for (int i = 0; i < n; ++ i) {if ((state&(1<<i)) && test(n, state-(1<<i), w)) {save[d] = i;  if (dfs(n, d+1, state-(1<<i), w))return 1;}}return 0;}int main(){int l, m, n, cases = 1;while (~scanf("%d%d%d",&l,&m,&n) && l+m+n) {for (int i = 0; i < n; ++ i)scanf("%d%d",&space[i],&weight[i]);printf("Case %d:\n",cases ++);memset(states, 0, sizeof(states));if (test(n, (1<<n)-1, 0.75*m) && !dfs(n, 0, (1<<n)-1, 0.75*m))puts("Impossible");}    return 0;}


0 0
原创粉丝点击