Shut the Box
Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 9 Solved: 5
[ Submit][ Status][ Web Board]
Description
Shut the Box is a one-player game that begins with a set of N pieces labeled from 1 to N. All pieces are initially "unmarked" (in the picture above, the unmarked pieces are those in an upward position). In the version we consider, a player is allowed up to T turns, with each turn defined by an independently chosen value V (typically determined by rolling one or more dice). During a turn, the player must designate a set of currently unmarked pieces whose numeric labels add precisely to V, and mark them. The game continues either until the player runs out of turns, or until a single turn when it becomes impossible to find a set of unmarked pieces summing to the designated value V (in which case it and all further turns are forfeited). The goal is to mark as many pieces as possible; marking all pieces is known as "shutting the box." Your goal is to determine the maximum number of pieces that can be marked by a fixed sequence of turns.
As an example, consider a game with 6 pieces and the following sequence of turns: 10, 3, 4, 2. The best outcome for that sequence is to mark a total of four pieces. This can be achieved by using the value 10 to mark the pieces 1+4+5, and then using the value of 3 to mark piece 3. At that point, the game would end as there is no way to precisely use the turn with value 4 (the final turn of value 2 must be forfeited as well). An alternate strategy for achieving the same number of marked pieces would be to use the value 10 to mark four pieces 1+2+3+4, with the game ending on the turn with value 3. But there does not exist any way to mark five or more pieces with that sequence.
Hint: avoid enormous arrays or lists, if possible.
Input
Each game begins with a line containing two integers, N, T where 1 ≤ N ≤ 22 represents the number of pieces, and 1 ≤ T ≤ N represents the maximum number of turns that will be allowed. The following line contains T integers designating the sequence of turn values for the game; each such value V will satisify 1 ≤ V ≤ 22. You must read that entire sequence from the input, even though a particular game might end on an unsuccessful turn prior to the end of the sequence. The data set ends with a line containing 0 0.
Output
You should output a single line for each game, as shown below, reporting the ordinal for the game and the maximum number of pieces that can be marked during that game.
Sample Input
Sample Output
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
vector<int> v[25];
void dfs(int x,int pos,int n,int state)
{
if(!x)
{
v[n].push_back(state);
return;
}
if(x>pos*(pos+1)/2) return;
for(int i=min(pos,x);i>=1;i--)
dfs(x-i,i-1,n,state|(1<<(i-1)));
}
int c[1<<22];
set<int> s1,s2; //s1 s2像一个接力棒一样
void bit_cal(int n)
{
for(int i=0;i<22;i++)
if(n&(1<<i)) c[n]++;
}
void init()
{
memset(c,0,sizeof(c));
for(int i=0;i<(1<<22);i++)
bit_cal(i);
for(int i=1;i<=22;i++)
{
v[i].clear();
dfs(i,i,i,0);
sort(v[i].begin(),v[i].end());
// printf("%d %d\n",i,v[i].size());
}
}
int main()
{
init();
// cout<<c[(1<<21)-1]<<endl;
int n,m,Tcase=0;
int t[25];
while(scanf("%d %d",&n,&m)==2)
{
if(!n&&!m) break;
for(int i=1;i<=m;i++)
scanf("%d",&t[i]);
s1.clear();
s1.insert(0);
set<int>::iterator it;
int ans=0;
for(int i=1;i<=m;i++)
{
int maxn=0,state;
for(it=s1.begin();it!=s1.end();it++)
{
// cout<<v[t[i]].size()<<endl;
for(int k=0;k<v[t[i]].size();k++)
{
if(v[t[i]][k]>=(1<<n)) break;
if((*it)&(v[t[i]][k])) continue;
state=(*it)|v[t[i]][k];
//cout<<state<<endl;
s2.insert(state);
maxn=max(maxn,c[state]);
}
}
// cout<<maxn<<endl;
if(!maxn) break;
ans=max(ans,maxn);
if(ans==n) break;
s1.clear();
for(it=s2.begin();it!=s2.end();it++)
s1.insert(*it);
s2.clear();
}
printf("Game %d: %d\n",++Tcase,ans);
}
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include <iostream>
#include <cstdio>
using namespace std;
int turn[30],n,m,ans;
int mark[30];
void dfs(int id,int rest,int num)
{
if(num>ans) ans=num;
if(ans==n) return;
if(id>=m) return;
if(id==m-1&&rest==0) return;
if(rest==0)
{
dfs(id+1,turn[id+1],num);
return;
}
for(int i=1;i<=n&&rest>=i;i++)
if(!mark[i])
{
mark[i]=1;
dfs(id,rest-i,num+1);
mark[i]=0;
}
}
int main()
{
int i,j;
while(scanf("%d %d",&n,&m)==2)
{
for(i=0;i<m;i++)
scanf("%d",&turn[i]);
ans=0;
memset(mark,0,sizeof(mark));
dfs(0,turn[0],0);
printf("%d\n",ans);
}
return 0;
}