HDU 1664
题目链接:
题意:
给一个数字n,一个数字,在满足数字每个位上拥有最少不同数字的前提下,该数字的最小值。
思路:
想到了在n的范围内,如果出现重复数就不在往下走的做法。但是依然有难处理的地方,就是如何保证不同数字最少。也想过对n个、十、百、千等每位分解出来讨论,然后维护一个区间,讨论0、1、2、3、4、5、6、7、8、9的区间。
然而最后都会卡在这个数到底有多长的条件下。
题解是用前向星来存,如果余数出现过就跳过的方法。剩下的实现方法都是可以自己做的。
值得注意的是string标准库的用法。
string str:
初始化 str = “” / str = string(“***”) / str - string(char a, int len)
连接 str += ‘*’
翻转 reverse(str.begin(), str.end())
输出 可以用数组循环的遍历方式输出%c,或者cout。
但是不能print(“%s”, str)
源码:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <queue>
#include <string>
using namespace std;
const int MAXN = 70000;
int n, anscnt;
int da[5];
string ans, curans;
struct Lv
{
int pre, val, cnt, d;
Lv(){}
Lv(int _pre, int _val, int _cnt, int _d){pre = _pre, val = _val, cnt = _cnt; d = _d;}
}que[MAXN];
int vis[MAXN];
bool BFS(int k)
{
memset(vis, 0, sizeof(vis));
int st, en;
st = en = 0;
que[en++] = Lv(-1, 0, 0, 0);
while(st < en){
Lv org = que[st++];
for(int i = 0 ; i < k ; i++){
int tval = (org.val * 10 + da[i]) % n;
if(vis[tval] || (st == 1 && da[i] == 0))
continue;
vis[tval] = 1;
if(tval == 0){
curans = "";
curans += da[i] + '0';
while(org.pre != -1){
curans += org.d + '0';
org = que[org.pre];
}
reverse(curans.begin(), curans.end());
return 1;
}
que[en++] = Lv(st-1, tval, org.cnt + 1, da[i]);
}
}
return 0;
}
int main()
{
while(scanf("%d", &n) != EOF && n){
ans = "";
anscnt = MAXN;
for(da[0] = 1 ; da[0] <= 9 ; da[0]++){
if(BFS(1)){
if(anscnt > (int)curans.size()){
anscnt = curans.size();
ans = curans;
}
}
}
if(anscnt == MAXN){
for(da[0] = 0 ; da[0] <= 9 ; da[0]++){
for(da[1] = da[0] + 1 ; da[1] <= 9 ; da[1]++){
if(BFS(2)){
if(anscnt > (int)curans.size()){
anscnt = curans.size();
ans = curans;
}
else if(anscnt == (int)curans.size() && ans > curans)
ans = curans;
}
}
}
}
cout << ans << endl;
}
return 0;
}