題目鏈接:點擊打開鏈接
簡單的搜索技巧與剪枝,不多說了心累,保存路徑。。。
//164K 0MS
//C++ 1331B
#include <cstring>
#include <cstdio>
int p[6]={100000,10000,1000,100,10,1}; //類似於迷宮方向數組的感覺
int n,sum,dis[6],z; //z爲遞歸的編號,防止重複路徑覆蓋,每一次遞歸編號都是不同的
int mx,f,x;
struct node
{
int pi; //前一次遞歸的編號
int num; //當前的剪出的數字
}q[33];
void dfs(int k,int m,int l,int w)
{
int i;
for(i=l;i<5;i++) //由當前位數開始查找到最後,因爲有前導零的情況,所以要記錄位數
{
int h=m; //當前要剪切的數字
if(k-h/p[i]>=0)
{
q[++z].pi=w; //記錄當前遞歸的編號
q[z].num=h/p[i]; //記錄剪下來的數字
dfs(k-h/p[i],h%p[i],i+1,z); //遞歸下一次的目標數,剩餘數
}
}
if(m<=k) //若當前數已經不大於當前目標數
{
if(mx<n-k+m) //更新mx
{
q[++z].pi=w; //記錄路徑
q[z].num=m;
x=z;f=0; //返回路徑起點編號
mx=n-k+m;
}
else if(mx==n-k+m)
{
f=1; //若最大值重複則標記,出現新的最大值時刪除標記
}
}
}
int main()
{
int m,i,j;
while(~scanf("%d%d",&n,&m)&&(n||m))
{
memset(dis,0,sizeof(dis));
f=0; //重複標記
x=-1; //路徑終點編號
z=0; //遞歸編號
mx=-1; //最接近切割數
for(i=0;i<6;i++) //找出這個數的位數;
if(m/p[i]>0)
break;
dfs(n,m,i,z); //當前目標數,當前數,當前數的位數對應的p數組下標,當前的遞歸次數
if(mx==-1)
printf("error\n");
else if(f)
printf("rejected\n");
else
{
printf("%d ",mx);
for(i=x,j=0;i!=0;i=q[i].pi) //順着前一個的下標從後往前找路徑出來
{
dis[j++]=q[i].num;
}
for(i=j-1;i>=0;i--)
{
printf("%d",dis[i]);
if(i)
printf(" ");
}
printf("\n");
}
}
return 0;
}
經歷過網絡賽心更累了,補了一下注釋。