Problem p00246 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <vector>

using namespace std;

// int N;
// int MS[101];
// vector<map<char,char> > howToGet;
// map<map<char,char>,char> dp[43];
// void dfs(const int kind,int wgt,map<char,char> v){
//   if(kind==0){
//     map<char,char> nv=v;
//     dfs(kind+1,wgt,nv);
//   }
//   else if(wgt==0)howToGet.push_back(v);
//   else if(kind==10)return;
//   else{
//     for(int i=0;i*kind<=10;i++){
//       if(wgt-i*kind>=0){
// 	map<char,char> nv=v;
// 	if(i>=1)nv[kind]=i;
// 	dfs(kind+1,wgt-i*kind,nv);
//       }
//     }
//   }
// }

// void dfs2(const int pos,const map<char,char> v,int cnt,int &maxVal,int
// preLast){
//   if(pos==(int)howToGet.size())return;
//   if(preLast/10+cnt<=maxVal)return;
//   // 1セット分取れるか
//   map<char,char> nv=v;
//   bool ok=true;
//   int sz=0;
//   for(map<char,char>::iterator
//   it=howToGet[pos].begin();it!=howToGet[pos].end();it++){
//     if(nv.count(it->first)==0
//        ||nv[it->first]-(it->second)<0){
//       ok=false;
//       break;
//     }
//     else{
//       nv[it->first]-=it->second;
//       sz+=it->second;
//     }
//   }
//   // 1セット取れるならとる
//   if(ok){
//     maxVal=max(maxVal,cnt+1);
//     dfs2(pos,nv,cnt+1,maxVal,preLast-sz);
//   }
//   // 取らずに次のセットへ
//   dfs2(pos+1,v,cnt,maxVal,preLast);
// }

// void greedy(int &maxVal,map<char,char> v){
//   for(int pos=0;pos<(int)howToGet.size();pos++){
//     while(1){
//       bool ok=true;
//       for(map<char,char>::iterator
//       it=howToGet[pos].begin();it!=howToGet[pos].end();it++){
// 	if(v.count(it->first)==0||v[it->first]-(it->second)<0){
// 	  ok=false;
// 	  break;
// 	}
//       }
//       if(ok){
// 	for(map<char,char>::iterator
// it=howToGet[pos].begin();it!=howToGet[pos].end();it++)
// 	  v[it->first]-=it->second;
// 	maxVal++;
//       }
//       else
// 	break;
//     }
//   }
// }

// int main(){
//   dfs(0,10,map<char,char>());
//   while(cin>>N&&N){
//     map<char,char> cnts;
//     int preLast=0;
//     for(int i=0;i<N;i++)cin>>MS[i];
//     for(int i=0;i<N;i++){
//       cnts[MS[i]]++;
//       preLast+=MS[i];
//     }
//     for(int i=0;i<43;i++)dp[i].clear();
//     int maxVal=0;
//     greedy(maxVal,cnts);
//     // cout<<maxVal<<endl;
//     // dfs2(0,cnts,0,maxVal,preLast);
//     cout<<maxVal<<endl;
//   }
//   return 0;
// }

int N;
int MS[101];
vector<vector<char>> howToGet;
map<vector<char>, char> dp;
void dfs(int kind, int wgt, const vector<char> &v) {
  if (kind == 0) {
    vector<char> nv = v;
    nv.push_back(0);
    dfs(kind + 1, wgt, nv);
  } else if (wgt == 0)
    howToGet.push_back(v);
  else if (kind == 10)
    return;
  else {
    for (int i = 0; i * kind <= 10; i++) {
      if (wgt - i * kind >= 0) {
        vector<char> nv = v;
        nv.push_back(i);
        dfs(kind + 1, wgt - i * kind, nv);
      }
    }
  }
}

int dfs2(const vector<char> &v) {
  if (dp.count(v) != 0)
    return dp[v];
  int res = 0;
  for (int pos = 0; pos < (int)howToGet.size(); pos++) {
    // 1セット分取れるか
    vector<char> nv = v;
    bool ok = true;
    for (int j = 1; j < (int)howToGet[pos].size(); j++) {
      nv[j] -= howToGet[pos][j];
      if (nv[j] < 0) {
        ok = false;
        break;
      }
    }
    // iセット取れるならとる
    if (ok)
      res = max(res, dfs2(nv) + 1);
  }
  return dp[v] = res;
}

int main() {
  dfs(0, 10, vector<char>());
  while (cin >> N && N) {
    vector<char> cnts;
    for (int i = 0; i < N; i++)
      cin >> MS[i];
    for (int i = 0; i <= 10; i++)
      cnts.push_back(0);
    for (int i = 0; i < N; i++)
      cnts[MS[i]]++;
    int a = min(cnts[9], cnts[1]);
    cnts[9] -= a;
    cnts[1] -= a;
    int b = min(cnts[8], cnts[2]);
    cnts[8] -= b;
    cnts[2] -= b;
    int c = min((int)cnts[8], (int)cnts[1] / 2);
    cnts[8] -= c;
    cnts[2] -= c;
    int res = dfs2(cnts) + a + b + c;
    cout << res << endl;
  }
  return 0;
}

Fixed submission:
#include <algorithm>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <vector>

using namespace std;

// int N;
// int MS[101];
// vector<map<char,char> > howToGet;
// map<map<char,char>,char> dp[43];
// void dfs(const int kind,int wgt,map<char,char> v){
//   if(kind==0){
//     map<char,char> nv=v;
//     dfs(kind+1,wgt,nv);
//   }
//   else if(wgt==0)howToGet.push_back(v);
//   else if(kind==10)return;
//   else{
//     for(int i=0;i*kind<=10;i++){
//       if(wgt-i*kind>=0){
// 	map<char,char> nv=v;
// 	if(i>=1)nv[kind]=i;
// 	dfs(kind+1,wgt-i*kind,nv);
//       }
//     }
//   }
// }

// void dfs2(const int pos,const map<char,char> v,int cnt,int &maxVal,int
// preLast){
//   if(pos==(int)howToGet.size())return;
//   if(preLast/10+cnt<=maxVal)return;
//   // 1セット分取れるか
//   map<char,char> nv=v;
//   bool ok=true;
//   int sz=0;
//   for(map<char,char>::iterator
//   it=howToGet[pos].begin();it!=howToGet[pos].end();it++){
//     if(nv.count(it->first)==0
//        ||nv[it->first]-(it->second)<0){
//       ok=false;
//       break;
//     }
//     else{
//       nv[it->first]-=it->second;
//       sz+=it->second;
//     }
//   }
//   // 1セット取れるならとる
//   if(ok){
//     maxVal=max(maxVal,cnt+1);
//     dfs2(pos,nv,cnt+1,maxVal,preLast-sz);
//   }
//   // 取らずに次のセットへ
//   dfs2(pos+1,v,cnt,maxVal,preLast);
// }

// void greedy(int &maxVal,map<char,char> v){
//   for(int pos=0;pos<(int)howToGet.size();pos++){
//     while(1){
//       bool ok=true;
//       for(map<char,char>::iterator
//       it=howToGet[pos].begin();it!=howToGet[pos].end();it++){
// 	if(v.count(it->first)==0||v[it->first]-(it->second)<0){
// 	  ok=false;
// 	  break;
// 	}
//       }
//       if(ok){
// 	for(map<char,char>::iterator
// it=howToGet[pos].begin();it!=howToGet[pos].end();it++)
// 	  v[it->first]-=it->second;
// 	maxVal++;
//       }
//       else
// 	break;
//     }
//   }
// }

// int main(){
//   dfs(0,10,map<char,char>());
//   while(cin>>N&&N){
//     map<char,char> cnts;
//     int preLast=0;
//     for(int i=0;i<N;i++)cin>>MS[i];
//     for(int i=0;i<N;i++){
//       cnts[MS[i]]++;
//       preLast+=MS[i];
//     }
//     for(int i=0;i<43;i++)dp[i].clear();
//     int maxVal=0;
//     greedy(maxVal,cnts);
//     // cout<<maxVal<<endl;
//     // dfs2(0,cnts,0,maxVal,preLast);
//     cout<<maxVal<<endl;
//   }
//   return 0;
// }

int N;
int MS[101];
vector<vector<char>> howToGet;
map<vector<char>, char> dp;
void dfs(int kind, int wgt, const vector<char> &v) {
  if (kind == 0) {
    vector<char> nv = v;
    nv.push_back(0);
    dfs(kind + 1, wgt, nv);
  } else if (wgt == 0)
    howToGet.push_back(v);
  else if (kind == 10)
    return;
  else {
    for (int i = 0; i * kind <= 10; i++) {
      if (wgt - i * kind >= 0) {
        vector<char> nv = v;
        nv.push_back(i);
        dfs(kind + 1, wgt - i * kind, nv);
      }
    }
  }
}

int dfs2(const vector<char> &v) {
  if (dp.count(v) != 0)
    return dp[v];
  int res = 0;
  for (int pos = 0; pos < (int)howToGet.size(); pos++) {
    // 1セット分取れるか
    vector<char> nv = v;
    bool ok = true;
    for (int j = 1; j < (int)howToGet[pos].size(); j++) {
      nv[j] -= howToGet[pos][j];
      if (nv[j] < 0) {
        ok = false;
        break;
      }
    }
    // iセット取れるならとる
    if (ok)
      res = max(res, dfs2(nv) + 1);
  }
  return dp[v] = res;
}

int main() {
  dfs(0, 10, vector<char>());
  while (cin >> N && N) {
    vector<char> cnts;
    for (int i = 0; i < N; i++)
      cin >> MS[i];
    for (int i = 0; i <= 10; i++)
      cnts.push_back(0);
    for (int i = 0; i < N; i++)
      cnts[MS[i]]++;
    int sum = 0;
    // for(int i=1;i<=9;i++)
    //   cout<<(int)cnts[i]<<" ";
    // cout<<endl;
    for (int i = 1; i <= 4; i++) {
      int a = min(cnts[i], cnts[10 - i]);
      cnts[i] -= a;
      cnts[10 - i] -= a;
      sum += a;
    }
    int a = cnts[5] / 2;
    cnts[5] -= 2 * a;
    sum += a;
    // cout<<sum<<endl;
    int res = dfs2(cnts) + sum;
    cout << res << endl;
  }
  return 0;
}