SRM588 KeyDungeonDiv1

来源:互联网 发布:程序员赚钱的方法 编辑:程序博客网 时间:2024/05/04 01:03

任意门:http://community.topcoder.com/stat?c=problem_statement&pm=12714


很典型的状压DP。

如果已经通过的是门A和门B的话,不论先过A还是先过B,用掉的钥匙数和得到的钥匙数是一样的。但是请注意:使用的白钥匙可能不一样。

换而言之,用于开红色门的白钥匙数可能不一样(同理,用于开绿门的白钥匙数也不一样,只需统计一个就可以了)

所以压缩的状态为已经通过的门,和剩余的红钥匙数(和在红门上使用的白钥匙数是互补的),去DFS吧= =


// BEGIN CUT HERE// END CUT HERE#line 5 "KeyDungeonDiv1.cpp"#include <cstdio>  #include <cstring>  #include <cctype>#include <cstdlib>  #include <ctime>  #include <climits>  #include <cmath>  #include <iostream>  #include <string>  #include <vector>  #include <set>  #include <map>  #include <list>  #include <queue>  #include <stack>  #include <deque>  #include <algorithm>  using namespace std;typedef long long ll;#define SZ(x) ((int)(x.size()))const int INF = 0x3f3f3f3f;int n, tot, ans;struct Door{int d1,d2;int k1,k2,k3;}door[12];int dp[1<<12][131];void dfs(int state,int key1,int key2,int key3){if (dp[state][key1]>0) return;dp[state][key1] = key1+key2+key3;if (ans<dp[state][key1]) ans=dp[state][key1];if (state==(1<<n)-1) return;for (int i=0;i<n;i++){if (state&(1<<i)) continue;int d1=door[i].d1, d2=door[i].d2, k1=door[i].k1, k2=door[i].k2, k3=door[i].k3;if (key1>=d1 && key2>=d2)dfs(state|(1<<i), key1-d1+k1, key2-d2+k2, key3+k3);else{int les = max(0,d1-key1)+max(0,d2-key2);if (key3>=les) dfs(state|(1<<i), max(0,key1-d1)+k1, max(0,key2-d2)+k2, key3-les+k3);}}}class KeyDungeonDiv1{public:int maxKeys(vector <int> doorR, vector <int> doorG, vector <int> roomR, vector <int> roomG, vector <int> roomW, vector <int> keys){int ret;n = SZ(doorR); tot = 1<<n;for (int i=0;i<n;i++){door[i].d1=doorR[i];door[i].d2=doorG[i];door[i].k1=roomR[i];door[i].k2=roomG[i];door[i].k3=roomW[i];}for (int i=0;i<tot;i++)for (int k=0;k<=130;k++)dp[i][k]=0;ans = 0;dfs(0,keys[0],keys[1],keys[2]);return ret = ans;}// BEGIN CUT HEREpublic:void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); if ((Case == -1) || (Case == 4)) test_case_4(); }private:template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }void verify_case(int Case, const int &Expected, const int &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }void test_case_0() { int Arr0[] = {1, 2, 3}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {0, 4, 9}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {0, 0, 10}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arr3[] = {0, 8, 9}; vector <int> Arg3(Arr3, Arr3 + (sizeof(Arr3) / sizeof(Arr3[0]))); int Arr4[] = {1, 0, 8}; vector <int> Arg4(Arr4, Arr4 + (sizeof(Arr4) / sizeof(Arr4[0]))); int Arr5[] = {3, 1, 2}; vector <int> Arg5(Arr5, Arr5 + (sizeof(Arr5) / sizeof(Arr5[0]))); int Arg6 = 8; verify_case(0, Arg6, maxKeys(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)); }void test_case_1() { int Arr0[] = {1, 1, 1, 2}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {0, 2, 3, 1}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {2, 1, 0, 4}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arr3[] = {1, 3, 3, 1}; vector <int> Arg3(Arr3, Arr3 + (sizeof(Arr3) / sizeof(Arr3[0]))); int Arr4[] = {1, 0, 2, 1}; vector <int> Arg4(Arr4, Arr4 + (sizeof(Arr4) / sizeof(Arr4[0]))); int Arr5[] = {0, 4, 0}; vector <int> Arg5(Arr5, Arr5 + (sizeof(Arr5) / sizeof(Arr5[0]))); int Arg6 = 4; verify_case(1, Arg6, maxKeys(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)); }void test_case_2() { int Arr0[] = {2, 0, 4}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {3, 0, 4}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {0, 0, 9}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arr3[] = {0, 0, 9}; vector <int> Arg3(Arr3, Arr3 + (sizeof(Arr3) / sizeof(Arr3[0]))); int Arr4[] = {8, 5, 9}; vector <int> Arg4(Arr4, Arr4 + (sizeof(Arr4) / sizeof(Arr4[0]))); int Arr5[] = {0, 0, 0}; vector <int> Arg5(Arr5, Arr5 + (sizeof(Arr5) / sizeof(Arr5[0]))); int Arg6 = 27; verify_case(2, Arg6, maxKeys(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)); }void test_case_3() { int Arr0[] = {5, 3, 0, 0}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {0, 1, 2, 1}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {0, 9, 2, 4}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arr3[] = {2, 9, 2, 0}; vector <int> Arg3(Arr3, Arr3 + (sizeof(Arr3) / sizeof(Arr3[0]))); int Arr4[] = {0, 9, 1, 1}; vector <int> Arg4(Arr4, Arr4 + (sizeof(Arr4) / sizeof(Arr4[0]))); int Arr5[] = {1, 1, 0}; vector <int> Arg5(Arr5, Arr5 + (sizeof(Arr5) / sizeof(Arr5[0]))); int Arg6 = 32; verify_case(3, Arg6, maxKeys(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)); }void test_case_4() { int Arr0[] = {9,5,10,8,4,3,0,8,4,1,3,9}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {9,10,0,8,9,4,3,8,1,8,10,4}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {1,2,0,2,3,3,5,3,1,3,0,5}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arr3[] = {5,2,5,0,5,2,3,4,0,0,5,2}; vector <int> Arg3(Arr3, Arr3 + (sizeof(Arr3) / sizeof(Arr3[0]))); int Arr4[] = {1,5,1,2,0,4,4,0,3,3,1,3}; vector <int> Arg4(Arr4, Arr4 + (sizeof(Arr4) / sizeof(Arr4[0]))); int Arr5[] = {5,0,1}; vector <int> Arg5(Arr5, Arr5 + (sizeof(Arr5) / sizeof(Arr5[0]))); int Arg6 = 16; verify_case(4, Arg6, maxKeys(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)); }// END CUT HERE};// BEGIN CUT HEREint main(){KeyDungeonDiv1 ___test;___test.run_test(-1);return 0;}// END CUT HERE


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 怀孕了好无聊怎么办 做表率我们怎么办心得 晚上左转逆行了怎么办 鼓浪屿船票买不到怎么办 信用卡逾期房贷批不下来怎么办 房贷逾期还款怎么办 网被垄断了怎么办? 百度搜索网页打不开怎么办? 原生家庭很糟糕怎么办 白色油漆变黄怎么办 白油漆家具泛黄怎么办 交通电子眼60分怎么办 被公司罚款了怎么办 公司对员工罚款怎么办 高一军训洗漱怎么办 吃精神病药发胖怎么办 神经病人不吃药怎么办 事故全责不赔钱怎么办 吃精神药物发胖怎么办 郑州出院限号怎么办 林场改革森林消防怎么办 网络课没有看完怎么办 福建省会计证未换怎么办 国税地税登记后怎么办 网上发票领不了怎么办 合肥餐饮怎么办环评 地税财务报表上传错误怎么办? 平安体检卡过期怎么办 到医院挂号后怎么办 一吹风就头痛怎么办 平安口袋e怎么办离职 学员学分卡号怎么办 华医网注册错了怎么办 医师继续教育学分不够怎么办 执业医师学分卡怎么办 护士学分5年没办怎么办 华医网职称录入错误怎么办 在北京没有学历怎么办 继续教育证书丢了怎么办 继续教育证丢了怎么办 继续教育档案丢了怎么办