暴搜DFS
当初在NOIP2015考场上的时候还是too young,这题只拿了15分,那时候什么都不懂……
考虑到如果不出任何顺子,那么我们可以贪心地出牌,肯定能得到最优解。于是我们在DFS爆搜的时候只要考虑顺子就好了。这样确实可以A掉UOJ147(因为数据比较弱?)然而UOJ151是数据加强(果然好强…),交上去就跪了。原因是有一些点是类似于把两个炸弹拆成四带二来打之类的……加了好多特判才A……
下面是151的代码,在判火箭的地方改一下应该就是147的代码了吧……
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 16
using namespace std;
int n, a[N], ans, cnt[5];
int calc()
{
int ret=0, temp;
memset(cnt,0,sizeof(cnt));
for(int i = 0; i <= 14; i++)
cnt[a[i]]++;
if(cnt[4])
{
temp=min(cnt[4],cnt[2]/2);
ret+=temp;
cnt[4]-=temp;
cnt[2]-=2*temp;
temp=min(cnt[4],cnt[1]/2);
ret+=temp;
cnt[4]-=temp;
cnt[1]-=2*temp;
}
if(cnt[3])
{
temp=min(cnt[3],cnt[2]);
ret+=temp;
cnt[3]-=temp;
cnt[2]-=temp;
temp=min(cnt[3],cnt[1]);
ret+=temp;
cnt[3]-=temp;
cnt[1]-=temp;
}
for(int i = 1; i <= 4; i++)
ret+=cnt[i];
if(cnt[1]>=2 && a[0] && a[1])
ret--;//火箭
return ret;
}
void dfs(int step)
{
if(step>=ans)return;
ans=min(ans,step+calc());
for(int i = 3; i <= 14; i++)
if(a[i]>=3)
for(int j = i+1; j <= 14; j++)
{
if(a[j]<3)break;
for(int k = i; k <= j; k++)a[k]-=3;
dfs(step+1);
for(int k = i; k <= j; k++)a[k]+=3;
}
for(int i = 3; i <= 14; i++)
if(a[i]>=2)
for(int j = i+1; j <= 14; j++)
{
if(a[j]<2)break;
if(j-i<2)continue;
for(int k = i; k <= j; k++)a[k]-=2;
dfs(step+1);
for(int k = i; k <= j; k++)a[k]+=2;
}
for(int i = 3; i <= 14; i++)
if(a[i]>=1)
for(int j = i+1; j <= 14; j++)
{
if(a[j]<1)break;
if(j-i<4)continue;
for(int k = i; k <= j; k++)a[k]--;
dfs(step+1);
for(int k = i; k <= j; k++)a[k]++;
}
for(int i = 2; i <= 14; i++)
{
if(a[i]==4)
{
for(int j = 2; j <= 14; j++)
{
if(j==i)continue;
if(a[j]==4)
{
a[i]=a[j]=0;
dfs(step+1);
a[i]=a[j]=4;
}
if(a[j]>=3)
for(int k = 2; k <= 14; k++)
{
if(k==i||k==j)continue;
if(a[k]>=2)
{
a[i]-=4;
a[j]-=2;
a[k]-=2;
dfs(step+1);
a[i]+=4;
a[j]+=2;
a[k]+=2;
}
}
if(a[j]>=2)
{
for(int k = 2; k <= 14; k++)
{
if(k==i||k==j)continue;
if(a[k]>=1)
{
a[i]-=4;
a[j]-=1;
a[k]-=1;
dfs(step+1);
a[i]+=4;
a[j]+=1;
a[k]+=1;
}
}
a[i]-=4;
a[j]-=2;
dfs(step+1);
a[i]+=4;
a[j]+=2;
}
}
}
if(a[i]==3)
{
for(int j = 2; j <= 14; j++)
{
if(j==i)continue;
if(a[j]>=2)
{
a[i]-=3;
a[j]-=1;
dfs(step+1);
a[i]+=3;
a[j]+=1;
}
if(a[j]>=3)
{
a[i]-=3;
a[j]-=2;
dfs(step+1);
a[i]+=3;
a[j]+=2;
}
}
}
}
}
int main()
{
int T;
scanf("%d%d",&T,&n);
while(T--)
{
memset(a,0,sizeof(a));
for(int i = 1, x, y; i <= n; i++)
{
scanf("%d%d",&x,&y);
if(x==1)x=14;
else if(x==0 && a[0])x=1;
a[x]++;
}
ans=calc();
dfs(0);
printf("%d\n",ans);
}
}