背景:这题做了大概五个小时,每次都在标记上出错。
思路:回溯,我先把军舰的长度按照由长到短依次排列,然后依次检索,特别注意变量l的使用,正是这个变量的使用,我的一段混乱代码才可以过。
题目中的数据很容易过,如果实在找不出错误,又不知道如何出数据,可以把第一组和第二组数据结合起来(一般人我不告诉他,哈哈)。代码如下,请自行理解。
学习:回溯算法:从一条路往前走,能进则进,不能进则退回来,换一条路再试。
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int shuchu[12][102],junjian1[102],jilu[12],ok,m;
int junjian[102],duiwu[12],l;
bool paixu(int a,int b)
{
return a>b;
}
void judge1(int k,int i,int j,int sum,int d,int j1)
{
if(ok||k>d) return;
junjian1[j]=1;
shuchu[i][sum]=junjian[j];
if(i==1&&sum==1) l=j;
if(k==d) {ok=1;jilu[i]=sum;return;}
if(k<d)
{
for(;j<=m;j++)
{
if(ok) return;
if(junjian1[j]) continue;
if(!junjian1[j]) judge1(k+junjian[j],i,j,sum+1,d,j1);
if(!ok) junjian1[j]=0;
}
}
}
void judge(int junjian[],int d,int m,int n,int i,int k)
{
for(int j=k;j<=m;j++)
{
if(junjian1[j]) continue;
if(!junjian1[j])
{
judge1(junjian[j],i,j,1,d,j);
if(!ok) junjian1[j]=0;
}
if(ok) return;
}
}
int main(void)
{
int n;
while(cin>>m>>n&&m&&n)
{
memset(junjian1,0,sizeof(junjian1));
memset(shuchu,0,sizeof(shuchu));
memset(jilu,0,sizeof(jilu));
memset(junjian,0,sizeof(junjian));
memset(duiwu,0,sizeof(duiwu));
for(int i=1;i<=m;i++) cin>>junjian[i];
for(int j=1;j<=n;j++) cin>>duiwu[j];
sort(junjian+1,junjian+m+1,paixu);
for(int i1=1;i1<=n;i1++)
{
ok=0;
judge(junjian,duiwu[i1],m,n,i1,1);
if(!ok)
{
int k1=l+1;
i1=1;
memset(shuchu,0,sizeof(shuchu));
memset(jilu,0,sizeof(jilu));
memset(junjian1,0,sizeof(junjian1));
judge(junjian,duiwu[i1],m,n,i1,k1);
}
}
for(int i2=1;i2<=n;i2++)
{
cout<<jilu[i2];
for(int j=1;j<=jilu[i2];j++)
{
cout<<' '<<shuchu[i2][j];
}
cout<<endl;
}
}
return 0;
}