HDU4474,POJ1465,HDU1226 一类数位限制倍数的BFS问题

HDU4474,POJ1465,HDU1226,URAL1495这些题目,首先是URAL1495,那天做这个第一个想法就是数位dp,但是没有推测出来,有段时间没做这个了,呃~然后采用了dfs的手法进行记忆化搜索,结果WA出翔了,搞了一下午,而后看了题解用数位DP解决了,但是也发现了一种比较稳妥的方法,比较清晰,而且网上刚好有个巨巨整理出了这一系列

可以戳这里  跳转

而后看了这位巨巨的大致方法做了一下URAL1495,学会了,然后又接下去做了这一个系列,这个方法很好很清晰,所以写下下来保存下来!

做这个系列期间也没有很利索的做完,比如POJ1465,当时我的队列是开在bfs里面的,结果就一直超时,最后随意试了一下才发觉的,交了我无数把啊,另外还有一些模0的问题需要注意,HDU1226稍微加了层迷雾,不过是进制转化罢了

HDU4474:

typedef struct Node {
    int num;
    int mod;
    int len;
};

bool vis[15];

int n,m;

int pre[10][10000 + 55][2];

queue<Node > q;

int Case = 0;

void init() {
    memset(pre,-inf,sizeof(pre));
    memset(vis,false,sizeof(vis));
}

bool input() {
    while(cin>>n>>m) {
        for(int i=0;i<m;i++) {
            int x;
            cin>>x;
            vis[x] = true;
        }
        return false;
    }
    return true;
}

void dfs(int pos,int mod) {
    if(pos == -1)return;
    dfs(pre[pos][mod][0],pre[pos][mod][1]);
    printf("%d",pos);
}

bool bfs() {
    while(!q.empty())q.pop();
    Node s,e;
    for(int i=1;i<10;i++) {
        if(!vis[i]) {
            s.num = i;
            s.mod = i%n;
            s.len = 1;
            pre[i][s.mod][0] = -1;
            q.push(s);
        }
    }
    while(!q.empty()) {
        s = q.front();
        q.pop();
        if(s.mod == 0) {
            dfs(s.num,s.mod);
            return true;
        }
        for(int i=0;i<10;i++) {
            if(!vis[i]) {
                e.num = i;
                e.mod = (s.mod * 10 + i)%n;
                e.len = s.len + 1;
                if(pre[e.num][e.mod][0] >= -1)continue;
                pre[e.num][e.mod][0] = s.num;
                pre[e.num][e.mod][1] = s.mod;
                q.push(e);
            }
        }
    }
    return false;
}

void cal() {
    printf("Case %d: ",++Case);
    if(!bfs()){puts("-1");return;}
    puts("");
}

void output() {

}

int main() {
    while(true) {
        init();
        if(input())return 0;
        cal();
        output();
    }
    return 0;
}

POJ1465:

typedef struct Node {
	int num;
	int mod;
	int len;
};

int nnum[100];

int n,m;

int pre[10][5500 + 55][2];

queue<Node > q;

void init() {
	memset(pre,-inf,sizeof(pre));
}

bool input() {
	while(cin>>n>>m) {
		for(int i=0;i<m;i++)cin>>nnum[i];
		return false;
	}
	return true;
}

void dfs(int pos,int mod) {
	if(pos == -1)return;
	dfs(pre[pos][mod][0],pre[pos][mod][1]);
	printf("%d",pos);
}

bool bfs() {
	while(!q.empty())q.pop();
	Node s,e;
	for(int i=0;i<m;i++) {
		if(nnum[i]) {
			s.num = nnum[i];
			s.mod = nnum[i]%n;
			s.len = 1;
			pre[nnum[i]][s.mod][0] = -1;
			q.push(s);
		}
	}
	while(!q.empty()) {
		s = q.front();
		q.pop();
		if(s.mod == 0) {
			dfs(s.num,s.mod);
			return true;
		}
		for(int i=0;i<m;i++) {
			e.num = nnum[i];
			e.mod = (s.mod * 10 + nnum[i])%n;
			e.len = s.len + 1;
			if(pre[e.num][e.mod][0] >= -1)continue;
			pre[e.num][e.mod][0] = s.num;
			pre[e.num][e.mod][1] = s.mod;
			q.push(e);
		}
	}
	return false;
}

void cal() {
	if(n == 0){puts("0");return ;}
	sort(nnum,nnum + m);
	if(!bfs()){puts("0");return;}
	puts("");
}

void output() {

}

int main() {
	while(true) {
		init();
		if(input())return 0;
		cal();
		output();
	}
	return 0;
}

HDU1226:

typedef struct Node {
    int num;
    int mod;
    int len;
};

bool vis[20 + 5];

int n,cc,m;

int pre[20 + 5][5000 + 55][2];

queue<Node > q;

int Case = 0;

void init() {
    memset(pre,-inf,sizeof(pre));
    memset(vis,false,sizeof(vis));
}

bool input() {
    while(cin>>n>>cc>>m) {
        char s[100000 + 5];
        for(int i=0;i<m;i++) {
            scanf("%s",s);
            int len = strlen(s);
            int tmp = 0;
            for(int i=0;i<len;i++) {
                if(s[i] >= '0' && s[i] <= '9')
                    tmp = tmp * 10 + s[i] - '0';
                else
                    tmp = tmp * 10 + s[i] - 'A' + 10;
            }
            vis[tmp] = true;
        }
        return false;
    }
    return true;
}

void dfs(int pos,int mod) {
    if(pos == -1)return;
    dfs(pre[pos][mod][0],pre[pos][mod][1]);
    if(pos < 10)printf("%d",pos);
    else printf("%c",pos - 10 + 'A');
}

bool bfs() {
    while(!q.empty())q.pop();
    Node s,e;
    for(int i=1;i<cc;i++) {
        if(vis[i]) {
            s.num = i;
            s.mod = i%n;
            s.len = 1;
            pre[i][s.mod][0] = -1;
            q.push(s);
        }
    }
    while(!q.empty()) {
        s = q.front();
        q.pop();
        if(s.len > 500)return false;
        if(s.mod == 0) {
            dfs(s.num,s.mod);
            return true;
        }
        for(int i=0;i<cc;i++) {
            if(vis[i]) {
                e.num = i;
                e.mod = (s.mod * cc + i)%n;
                e.len = s.len + 1;
                if(pre[e.num][e.mod][0] >= -1)continue;
                //cout<<e.num<<e.mod<<"******"<<endl;
                pre[e.num][e.mod][0] = s.num;
                pre[e.num][e.mod][1] = s.mod;
                q.push(e);
            }
        }
    }
    return false;
}

void cal() {
    if(n == 0) {
        if(vis[0])puts("0");
        else puts("give me the bomb please");
        return ;
    }
    if(!bfs()){puts("give me the bomb please");return ;}
    puts("");
}

void output() {

}

int main() {
    int t;
    cin>>t;
    while(t--) {
        init();
        if(input())return 0;
        cal();
        output();
    }
    return 0;
}

URAL1495:

int n;

typedef struct Node {
	int len;
	int digit;
	int mod;
};

int pre[3][1000000 + 55][2];

void init() {
	memset(pre,-inf,sizeof(pre));
}

bool input() {
	while(cin>>n) {
		return false;
	}
	return true;
}

void dfs(int digit,int mod) {
	if(digit == -1)return ;
	dfs(pre[digit][mod][0],pre[digit][mod][1]);
	printf("%d",digit);
}

bool bfs() {
	Node s,e;
	queue<Node> q;
	for(int i=1;i<=2;i++) {
		s.digit = i;
		s.mod = i%n;
		s.len = 1;
		pre[s.digit][s.mod][0] = -1;
		q.push(s);
	}
	while(!q.empty()) {
		s = q.front();
		q.pop();
		if(s.len > 30)return false;
		if(s.mod == 0) {
			dfs(s.digit,s.mod);
			return true;
		}
		for(int i=1;i<=2;i++) {
			e.digit = i;
			e.len = s.len + 1;
			e.mod = (s.mod * 10 + i)%n;
			if(pre[e.digit][e.mod][0] >= -1)continue;
			pre[e.digit][e.mod][0] = s.digit;
			pre[e.digit][e.mod][1] = s.mod;
			q.push(e);
		}
	}
	return false;
}

void cal() {
	if(n%10 == 0 || n%10 == 5) {puts("Impossible");return;}
	if(!bfs()){puts("Impossible");return;}
	puts("");
}

void output() {

}

int main() {
	while(true) {
		init();
		if(input())return 0;
		cal();
		output();
	}
	return 0;
}

时间: 2025-01-10 19:19:54

HDU4474,POJ1465,HDU1226 一类数位限制倍数的BFS问题的相关文章

51nod四级题(第一波汇总)

1051 最大子矩阵和() 思路: 用前缀和维护成块 然后 和 最大子序列和 同理.前缀和这块 O(n2)  后面最大子序列和 O(n),O(n3). 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int maxn = 500 + 5; 5 6 LL M[maxn][maxn], sum[maxn][maxn];// 第i行前j列的和 7 8 int main() 9 { 10

2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror) 体验记

原文链接https://www.cnblogs.com/zhouzhendong/p/CF1070.html 比赛网址:http://codeforces.com/contest/1070 感受 本来只打算玩玩的. 结果玩的海星. 我做 A 题的时候可能比较浮躁吧,各种傻错误,爆了 7 个罚时. 我 A 还没过,cly 神仙已经把 CDK 切光了. 4点半过一会儿,各自回家.cly 要剃头,就咕咕咕了.我本来也要剃的,后来临时决定先打题. 然后过了 A ,顺手切掉了 H 和 F ,开了 E ,猜

[hdu 3652]数位dp解决数的倍数问题

原以为很好的理解了数位dp,结果遇到一个新的问题还是不会分析,真的是要多积累啊. 解决13的倍数,可以根据当前余数来推,所以把当前余数记为一个状态就可以了. #include<bits/stdc++.h> using namespace std; int dp[20][13][2][10]; int b[20]; int dfs(int pos,int preok,int rem,int th,int pre) { if (pos==-1) { if (rem==0&&th==

数位类统计问题--数位DP

有一类与数位有关的区间统计问题.这类问题往往具有比较浓厚的数学味道,无法暴力求解,需要在数位上进行递推等操作.这类问题往往需要一些预处理,这就用到了数位DP. 本文地址:http://www.cnblogs.com/archimedes/p/numerical-digit-dp.html,转载请注明源地址. 基础知识 [l,r] 意为 l<=且<=r的数 [l,r) 意为 l<=且< r的数 (l,r] 意为 l<且<=r的数 (l,r) 意为 l<且< r

数位计数问题

在信息学竞赛中,有一类难度不大但异常麻烦的问题--数位计数问题, 这类问题的主要特点是询问的答案和一段连续的数的各个数位相关,并且需要对时间效率有一定要求. 由于解决这类问题往往意味着巨大的代码量,而众多的特 殊情况又意味着出现错误的巨大可能性,因此很少有人愿意解决此类问题, 但只要掌握好的方法,解决这类问题也并非想象中的那样困难------<<数位计数问题解法研究>>高逸涵. 其实数位DP或者说数位计数问题没这么难,只要构造出合适的状态,就能解决. 动态规划的核心就是在于状态的设

ACM学习历程—HDU5587 Array(数学 &amp;&amp; 二分 &amp;&amp; 记忆化 || 数位DP)(BestCoder Round #64 (div.2) 1003)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5587 题目大意就是初始有一个1,然后每次操作都是先在序列后面添加一个0,然后把原序列添加到0后面,然后从0到末尾,每一个都加上1. 例如:a0, a1, a2 => a0, a1, a2, 1, a0+1, a1+1, a2+1 题解中是这么说的:“ 其实Ai为i二进制中1的个数.每次变化A{k+2^i}=A{k}+1,(k<2^?i??)不产生进位,二进制1的个数加1.然后数位dp统计前m个数二

数位dp初步——数位dp的两种方式

数位dp:一类统计区间[L,R]内某种符合规定的数字个数的题目.特征是R的范围会很大,O(N)范围内无法完成. 一般而言,解决这类题目有两种方式,一种是递推,另一种是记忆化搜索. 递推: 1)利用dp求出数组f[i][j](表示有i位,最高位为j的数字中符合要求的数字的个数) 2)根据给出的[L,R],利用f[]统计答案 记忆化搜索: 1 int dfs(int pos,int pre,int lim){//当前位置 前一位的数字 是否有限制 2 if(pos<=0)return 1; 3 if

HDU 4507 (鬼畜级别的数位DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4507 题目大意:求指定范围内与7不沾边的所有数的平方和.结果要mod 10^9+7(鬼畜の元凶) 解题思路: 与7不沾边的数需要满足三个条件. ①不出现7 ②各位数和不是7的倍数 ③这个数不是7的倍数 这三个条件都是基础的数位DP. 但是这题要统计的不是符合条件个数,而是平方和. 也就是说在DP时候,要重建每个数,算出平方,然后求和. 需要维护三个值(推荐使用结构体), 假定dfs推出返回的结构体是

CF 55D Beautiful numbers (数位DP)

题意: 如果一个正整数能被其所有位上的数字整除,则称其为Beautiful number,问区间[L,R]共有多少个Beautiful number?(1<=L<=R<=9*1018) 思路: 数字很大,不能暴力.但是想要知道一个数是否为Beautiful number时,至少得等到它的所有位都出现吧?不然如何确定其实可以被整除的呢? 分析一下,类似2232和3232等这样的数字,这两个只是出现了2和3而已,他们的lcm都是6,所以有可以压缩统计的地方就是lcm,开一维来存储.接下来考虑