您的位置:首页 > 其它

poj 3373 Changing Digits

2012-07-18 09:12 381 查看
http://poj.org/problem?id=3373

DFS+强力剪枝

伤不起呀 自己写怎么都写不出来 最后还看开了别人的解题报告

思维能力还是不够呀

推荐解题报告:/article/1968975.html

代码及其注释:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<algorithm>
#include<set>

using namespace std;

const int N=105;
char s
;
int a
;
int change
[10005];//表示 区间0~i 模为j 改变多少数是无解的
int K;
int n;
int mod
[10];//从0位开始 第i位为 j 时对K取得模
int dpmod(int x,int k)
{
if(mod[x][k]!=-1)
return mod[x][k];
if(x==0)
{
mod[x][k]=k%K;
return mod[x][k];
}
mod[x][k]=(dpmod(x-1,k)*10)%K;
return mod[x][k];
}
int findmod()//求当前数组对K的模
{
int m=0;
for(int i=0;i<n;++i)
{
m=(m+dpmod(i,a[i]))%K;
}
return m;
}
int I=1;
bool Dfs(int x,int renum,int Mod)//0~x区间  re准许改变几个 Mod为模
{
if(Mod==0)
return true;
if(x<0||renum<=0)
return false;
if(renum<=change[x][Mod]||renum>x+1)//关键剪枝
return false;
for(int i=x;i>=0;--i)//找小的  从高位到低位
{
for(int j=(i<n-1)?0:1;j<a[i];++j)
{

int temp=a[i];
a[i]=j;
int k=(Mod-mod[i][temp]+mod[i][j]+K)%K;
if(Dfs(i-1,renum-1,k))
return true;
a[i]=temp;
}
}
for(int i=0;i<=x;++i) 找大的 从低位到高位
{
for(int j=a[i]+1;j<10;++j)
{
int temp=a[i];
a[i]=j;
int k=(Mod-mod[i][temp]+mod[i][j]+K)%K;
if(Dfs(i-1,renum-1,k))
return true;
a[i]=temp;
}
}
change[x][Mod]=renum;//记录
return false;
}
void begin()
{
for(int j=0;j<10;++j)
{
dpmod(n-1,j);
}
}
int main()
{
while(scanf("%s",s)!=EOF)
{
scanf("%d",&K);
getchar();
n=strlen(s);
for(int i=0;i<n;++i)
{
a[i]=s[n-i-1]-'0';
}
memset(mod,-1,sizeof(mod));
memset(change,-1,sizeof(change));
begin();
int k=findmod();
for(int i=1;i<=n;++i)
{
if(Dfs(n-1,i,k))
{break;}
}
for(int i=n-1;i>=0;--i)
printf("%d",a[i]);
printf("\n");
}
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: