1. 程式人生 > >gym - 101673I Twenty Four, Again (表達式樹枚舉)

gym - 101673I Twenty Four, Again (表達式樹枚舉)

blank 好處 sca div oid %d 點運算符 .net details

題意及思路

模擬場上用一般方法枚舉非常麻煩,一個小時沒寫出來,還是自己太菜了。。。用表達式樹枚舉有一個好處,判斷需不需要加括號非常方便,只有當前節點運算符的優先級高於子節點的時候,才需要給子節點加一個括號。

代碼:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
int cost[] = {0,1,1,2,2,3,1,2,2,3,3,4,2,3,3,4,4,5,3,4,4,5,5,6};
int ans = INF, num_cnt, flag_cnt;
int a[10], sum;
int b[5] = {0, 1, 2, 3, 4}, c[10];
struct node{
	int val, ls, rs;
};
node tr[110];
void init() {
   tr[1].ls=2;tr[1].rs=3;tr[2].ls=4;tr[2].rs=5;tr[3].ls=6;tr[3].rs=7; tr[8].ls=9;tr[8].rs=10;tr[9].ls=11;tr[9].rs=12;tr[11].ls=13;tr[11].rs=14; tr[15].ls=16;tr[15].rs=17;tr[16].ls=18;tr[16].rs=19;tr[19].ls=20;tr[19].rs=21; tr[22].ls=23;tr[22].rs=24;tr[24].ls=25;tr[24].rs=26;tr[25].ls=27;tr[25].rs=28; tr[29].ls=30;tr[29].rs=31;tr[31].ls=32;tr[31].rs=33;tr[33].ls=34;tr[33].rs=35; } bool is_leaf(int x) { return (tr[x].ls == 0) && (tr[x].rs == 0); } int op(int x, int y, int flag) { if(x == -INF || y == -INF) return -INF; if(flag == 0) return x + y; if(flag == 1) return x - y; if(flag == 2) return x * y; if((y == 0) || (flag == 3 && (x % y) != 0 )) return -INF; return x / y; } void build_tree(int x) { if(tr[x].ls == 0 && tr[x].rs == 0) { tr[x].val = a[b[++num_cnt]]; return; } else { tr[x].val = c[++flag_cnt]; build_tree(tr[x].ls); build_tree(tr[x].rs); } } int cal(int x) { if(tr[x].ls == 0 && tr[x].rs == 0) return tr[x].val; if(tr[x].val >= 2) { if(!is_leaf(tr[x].ls) && tr[tr[x].ls].val < 2) sum++; if(!is_leaf(tr[x].rs) && tr[tr[x].rs].val < 2) sum++; } return op(cal(tr[x].ls), cal(tr[x].rs), tr[x].val); } int main() { for (int i = 1; i <= 4; i++) scanf("%d", &a[i]); int now_state = 0; init(); do { for (int t = 0; t < 5; t++) { for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) for (int k = 0; k < 4; k++) { c[1] = i, c[2] = j, c[3] = k; flag_cnt = num_cnt = 0; sum = cost[now_state] * 2; build_tree(7 * t + 1); int now = cal(7 * t + 1); if(now == 24) { ans = min(ans, sum); } } } now_state++; }while(next_permutation(b + 1, b + 1 + 4)); if(ans == INF) printf("impossible\n"); else printf("%d\n", ans); }

  

gym - 101673I Twenty Four, Again (表達式樹枚舉)