vijos[P1054] luogu[P2662] 牛场围栏 (数论+最短路,(DP可水过))
来源:互联网 发布:复制别人的淘宝店铺 编辑:程序博客网 时间:2024/05/09 11:22
描述John计划为他的牛场建一个围栏,以限制奶牛们的活动。他有N种可以建造围栏的木料,长度分别是l1,l2…lN,每种长度的木料无限。修建时,他将把所有选中的木料拼接在一起,因此围栏的长度就是他使用的木料长度之和。但是聪明的John很快发现很多长度都是不能由这些木料长度相加得到的,于是决定在必要的时候把这些木料砍掉一部分以后再使用。不过由于John比较节约,他给自己规定:任何一根木料最多只能削短M米。当然,每根木料削去的木料长度不需要都一样。不过由于测量工具太原始,John只能准确的削去整数米的木料,因此,如果他有两种长度分别是7和11的木料,每根最多只能砍掉1米,那么实际上就有4种可以使用的木料长度,分别是6, 7, 10, 11。Clevow是John的牛场中的最聪明的奶牛,John请她来设计围栏。Clevow不愿意自己和同伴在游戏时受到围栏的限制,于是想刁难一下John,希望John的木料无论经过怎样的加工,长度之和都不可能得到她设计的围栏总长度。不过Clevow知道,如果围栏的长度太小,John很快就能发现它是不能修建好的。因此她希望得到你的帮助,找出无法修建的最大围栏长度。
输入格式输入的第一行包含两个整数N, M (1<N<100, 0<=M<3000),分别表示木料的种类和每根木料削去的最大值。以下各行每行一个整数li(1<li<3000),表示第i根木料的原始长度。输出格式输出仅一行,包含一个整数,表示不能修建的最大围栏长度。如果任何长度的围栏都可以修建或者这个最大值不存在,输出-1。样例1样例输入1[复制]2 17 11样例输出1[复制]15限制各个测试点1秒来源WinterCamp 2002
DP水过(luogu上DP可水过, vijos上会WA)
可行性dp,f[j]表示组成j长度是否可行,只要任意j-任意一根可生成的木棒长度可行就可以了,而目标是找到第一根不可行的,输出即可,注意预处理的时候判爆负数 ————luogu题解
代码:
#include <cstdio>#include <iostream>#include <string>#include <algorithm>using namespace std;int n, m, vis[1200000], f[2211111];int c[9211111];int main() { cin>>n>>m; for(int i = 1; i <= n; i++) { int x; scanf("%d", &x); for(int j = 0; j <= m && x - j; j++) { if(!vis[x - j]) { vis[x - j] = 1; c[++c[0]] = x - j; f[x - j] = 1; if(x - j == 1) { cout<< - 1 <<endl; return 0; } } } } for(int i = 1; i <= c[0]; i++) { int now = c[i]; for(int j = 0; j <= 100010; j++) { if(f[j - c[i]]) f[j] = 1; } } for(int j = 100010; j >= 0; j--) { if(!f[j]) { cout<<j<<endl; return 0; } }}
正解最短路
- 首先把一开始能弄出的木棍长度处理出来
- 找一个最小的, 设为min_length。 若最小的为1,则输出-1;
- 然后抽象的把0 - min_length - 1 的每一个数看成一个点,某些长度%min_length后,一定在这之间。
- 可以发现,如果我们能够组成某个长度x, 且 y = x % min_length; 又设X = y + i * min_length,则我们一定能够组成所有的X 且X满足下列关系(X%min_length == y);
- 如果不能组成呢?那么我们一定不能组成任意一个X使得(X%min_length == y); 也就是说,不能组成的最大长度是无限大,此时无解,输出-1。
- 如果能组成,我们只保存一个最小的x(x一定大于min_length),那么x - min_length 一定不能被组成。
- 如果余数为 0 - min_length - 1的长度 都能组成,则找一个最大的x ,则x - min_length 为最大的不能组成的长度。
- 所以,抽象出min_length - 1 个点,用dis[i] 表示余数为i的最小长度x。根据一开始的木棍长度,首先得到dis[i]的初始值,然后边走边建边。跑spfa即可
- 这个建边过程是边跑spfa边建边,且不用存每个点可连向那些点,因为对于可以组成的i,其他的每个点都可以与i相连,即这边是它们共有的。
- 为什么要边跑spfa边建边呢?因为对当前i,有一个j,(dis[i]+dis[j])%min_length == X 且dis[X]并未被更新,为初始极大INF,则建的边表中肯定不含这个点! 这时候把这个点加入表中。
代码:
#include <cstdio>#include <iostream>#include <string>#include <algorithm>#include <queue>#include <vector>using namespace std;#define debug cout<<"Orzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"<<endl;const int INF = 2047483647;int dis[3426];int c[422567], vis[5122567];int n,m;queue <int> q;vector <int> v;int min_length = INF;int max_length = -5;int iv[3456];int spfa() { for(int i = 0; i <= min_length; i++) { dis[i] = INF; } for(int i = 1; i <= c[0]; i++) {// cout<<now<<' '<<i<<' '<<c[i]<<' '<<endl; int now = c[i] % min_length; if(dis[now] == INF || dis[now] > c[i]) { dis[now] = c[i]; q.push(now); } }// debug; while(!q.empty()) { int now = q.front(); q.pop(); vis[now] = 0; if(!iv[now]) { v.push_back(now); iv[now] = 1; } for(int i = 0; i < v.size(); i++) { int nn = (dis[v[i]] + dis[now]) % min_length; if(dis[nn] > dis[now] + dis[v[i]]) { dis[nn] = dis[now] + dis[v[i]];// if(nn_mod == 3) {// cout<<dis[nn_mod] <<' '<<"dis["<<now_mod<<"] = "<<dis[now_mod] << ' '<<nn<<endl;// } if(!vis[nn]) { vis[nn] = 1; q.push(nn); } } } } for(int i = 0; i < min_length; i++) {// cout<<i<<' '<<dis[i]<<' '<<min_length<<' '<<endl; if(dis[i] < INF) { max_length = max(max_length, dis[i]); } else return -1; } return max_length - min_length;}int main() { cin>>n>>m; for(int i = 1; i <= n; i++) { int x; scanf("%d", &x); for(int j = 0; j <= m && x - j; j++) if(!vis[x - j]) { vis[x - j] = 1; c[++c[0]] = x - j; min_length = min(min_length , c[c[0]]); if(x - j == 1) { cout<< - 1 <<endl; return 0; } } } cout<<spfa()<<endl;// cout<<spfa(); return 0;}
1 0
- vijos[P1054] luogu[P2662] 牛场围栏 (数论+最短路,(DP可水过))
- luogu2662 牛场围栏(数论+最短路)
- 洛谷 P2662 牛场围栏
- 【背包->最短路】洛谷2662[牛场围栏]题解
- 牛场围栏详解
- Luogu P2384 最短路
- Vijos 1082 最短路
- 最短路(djstra过)
- 【最短路】Vijos P1046 观光旅游
- zoj3408(最短路+dp)
- BZOJ1003(最短路+DP)
- [Vijos 2024]无向图最短路径 (最短路)
- Luogu 1280(dp)
- Luogu 1282(dp)
- Luogu 1387(dp)
- Luogu 1156(dp)
- Luogu 1141(dp)
- vijos p1285(最短路变形+计数)
- Runtime的几个小例子
- win10 cpu占用率过高的解决办法
- Yii2框架 model方法下setAttributes用法(自定义model 添加方法)
- YYII框架中表单提交出现Bad Request (#400)---Unable to verify your data submission的错误解决方法
- 实验室(搜索->记忆化搜索->动规优化)
- vijos[P1054] luogu[P2662] 牛场围栏 (数论+最短路,(DP可水过))
- 提高mysql千万级大数据SQL查询优化30条经验(Mysql索引优化注意)
- C语言 九九乘法表
- 高精除
- LruCache
- c#批量插入数据到数据库【支持事务操作】
- 一会儿的谈话
- RunLoop 和 RunTime 的一些见解
- TODO:Node.js pm2使用方法