【 OJ 】 HDOJ1059 18年12月23日14:37 [ 51 ]
阿新 • • 發佈:2018-12-23
Time Limit Exceeded
直接暴搜.....死的很安詳
沒辦法...第一個想法就是這個:
# include<iostream> # include<algorithm> //# include<Windows.h> using namespace std; int n[6] = { 0 }; int ans, total, flag; int Visit[6]; void OUT(bool b) { static int index = 0; if (index)cout << endl; cout << "Collection #" << ++index << ":" << endl; if (b) { cout << "Can be divided." << endl; } else { cout << "Can't be divided." << endl; } } int INput(void) { int total_ = 0; for (int i = 0; i < 6; i++) { cin >> n[i];//錄入彈珠資訊 Visit[i] = n[i]; total_ += (i+1)*n[i]; } return total_; } void Fen(int index) {//index 層數一共6層,i第幾個物品 n[i]為該層有的物品數 for (int i = index; i < 6 && !flag; i++) { if (!index) {//0 層 ans =0;初始化訪問表 ans = 0; for (int j = 0; j < 6; j++) { Visit[j] = n[j]; } //初始化訪問表 } if (!Visit[i])continue; for (int k = 0; k <= n[i]; k++) {//首先不拿---直到拿n[i]個 Visit[i] -= k;//先拿K個 ans += (i + 1)*k; //得到K個總價值 if (ans < (total / 2)) {//價值小於目標數 Fen(i + 1);//遞迴到下一層 ans -= (i + 1)*k; //拿回的東西放回去 Visit[i] += k; } else if (ans == total / 2) { flag = true; return;//找到並返回 } else {//價格已經超出了 剪枝 ans -= (i + 1)*k; //東西放回去 結束 Visit[i] += k; return; } } } } int main() { total = INput();//拿到第一個輸入的價值 while (!((*max_element(n, n + 6)) == 0)) {//全0不做 if (total & 1)OUT(false);//總價值為奇數不可分割 else {//嘗試分割 flag = false;//未找到 Fen(0);//從0開始找 if (flag)OUT(true); else OUT(false); } total = INput();//錄入下一次資訊 } system("pause"); return 0; }
因為超時所以不知道準確答案,因此我寫了個檢測......用的別人正確的AC碼做參考:隨機生成了10W個數據顯示是對的
# include<iostream> # include<algorithm> #include <cstdio> #include <cstring> //# include<Windows.h> using namespace std; int n[6] = { 0 }; int a[6]; int ans, total, flag; int Visit[6]; const int SIZE = 120000 + 16; int dp[SIZE]; void Fen(int index) {//index 層數一共6層,i第幾個物品 for (int i = index; i < 6 && !flag; i++) { if (!index) {//0 層 ans =0;初始化訪問表 ans = 0; for (int j = 0; j < 6; j++) { Visit[j] = n[j]; } //初始化訪問表 } if (!Visit[i])continue; for (int k = 0; k <= n[i]; k++) {//首先不拿---直到拿n[i]個 Visit[i] -= k;//先拿K個 ans += (i + 1)*k; //得到K個總價值 if (ans < (total / 2)) {//價值小於目標數 Fen(i + 1);//遞迴到下一層 ans -= (i + 1)*k; //拿回的東西放回去 Visit[i] += k; } else if (ans == total / 2) { flag = true; return;//找到並返回 } else {//價格已經超出了 剪枝 ans -= (i + 1)*k; //東西放回去 結束 Visit[i] += k; return; } } } } void RAND(void) { total = 0; for (int i = 0; i < 6; i++) { n[i] = rand() % 5 + 1; a[i] = n[i]; Visit[i] = n[i]; total += (i + 1)*n[i]; } } bool My(void) { if (total & 1)return false;//總價值為奇數不可分割 else {//嘗試分割 flag = false;//未找到 Fen(0);//從0開始找 if (flag)return true; else return false; } } bool check() { for (int i = 0; i<6; i++) if (a[i] != 0) return true; return false; } bool YO(void) { int sum; int t = 0; while (true) { sum = 0; for (int i = 0; i<6; i++) { sum += (i + 1)*a[i]; } if (!check()) break; if (sum % 2 == 1) { return false; } else { memset(dp, -1, sizeof(dp)); int k = sum / 2; dp[0] = 0; for (int i = 0; i<6; i++) { for (int j = 0; j <= k; j++) { if (dp[j] >= 0) { dp[j] = a[i]; } else if (j<(i + 1) || dp[j - (i + 1)] <= 0) { dp[j] = -1; } else { dp[j] = dp[j - (i + 1)] - 1; } } } if (dp[k] >= 0) { return true; } else { return false; } } } } int main() { bool re1, re2; int index = 0; while((index+1)<10000){ cout << ++index << endl; RAND(); re1 = My(); re2 = YO(); if (re1 != re2) { cout << "出現不同結果:" << endl; cout << "--------------------" << endl; cout << "MY:" << re1 << endl; cout << "--------------------" << endl; cout << "--------------------" << endl; cout << "YO:" << re2 << endl; cout << "--------------------" << endl; cout << "--------------------" << endl; cout << "n 的情況: " << endl; for (int i = 0; i<6; i++) { cout <<i+1<<" : "<< a[i] << " "<<n[i]<<endl; } cout << "--------------------" << endl; getchar(); } } system("pause"); return 0; }