过河
来源:互联网 发布:艾瑞排名 数据雷达 编辑:程序博客网 时间:2024/05/06 02:37
http://www.rqnoj.cn/Problem_17.html
一、思路
刚开始什么也不想,简单动态规划 40个得分点
后面加上了空间的优化:
每次计算其实只需T+1个长度的数组来记忆,所以就用了伪循环队列
利用i % (T+1) hash实现
还是40个得分点
时间优化:
f[i] = min( f[i-t] ,f[i-t+1]...f[i-s])+del[i] 其中i为石子时del[i] = 1 否则为0
f[i]的改变就在于它这个位置是否有石子,以及它前t->s的状态
如果两个石子的距离大于了T,那么第a[i],和a[i+1]之间的石子状态将相同
如果S==T 那么要单独处理,否则还是L*M a[i]%s ==0
s=2 t=3 l=100
3 10
1 3 5 2 3 2 2 2 2 2
0 1 2 3 4 5 6 7 8 9
所以可以直接跳至下一个石子位置
90个得分点
#include <iostream.h>#define MAX_INT 999int delTa(int * a, int m, int k){int i=0;for (i=0; i<m; i++){if (k==a[i]) {return 1;}}if (i>=m) {return 0;}}int main(){ int i, j, l, s, t, m;int *a, *f;int beg;int p = 0;cin>>l>>s>>t>>m;a = new int[m];f = new int [t+1];//读入石子for (i=0; i<m; i++){cin>>a[i];}//冒泡排序石子for (i=1; i<m; i++){for (j=0; j<m-i; j++){if (a[j] > a[j+1]){a[j] = a[j] + a[j+1];a[j+1] = a[j] - a[j+1];a[j] = a[j] - a[j+1];}}}if (s==t){j = 0;for (i=0; i<m; i++){if (a[i] % s == 0){j++;}}cout<<j;return 0;}f[0] = 0;for (i=1; i<l+t; i++){int pos = i%(t+1);int del;//int del = delTa(a, m, i); if (i<a[p]) {if (p-1>=0 && i>a[p-1]+t){i = a[p]-1;continue;}else{del = 0;}//del = 0;}else if (i==a[p]){del = 1;}else {p = p+1<m ? p+1 : m-1;if (i==a[p]){del = 1;}else if (i>a[p-1]+t && i<a[p]){i = a[p]-1;continue;}else if (i>a[p]+t && i<l){i = l-1;continue;}else{del = 0;}}f[pos] = MAX_INT; for (j=s; j<=t; j++){int forePos = (i-j) % (t+1);if (i-j>=0 && f[pos]>f[forePos] + del){f[pos] = f[forePos] + del;}}//cout<<i<<':'<<f[i%(t+1)]<<' ';}j = MAX_INT;for (i=l; i<l+t; i++){if (j>f[i%(t+1)]){j = f[i%(t+1)];}}cout<<j;delete []a;delete []f;return 0;}
省下的那个得分点错在了哪里?
1、原先的伪循环队列有点hash意思,如果从1-L,那么不会出现重叠
但是如果时间优化就是调到下个石子可能会出现这种情况
0 1 2 本该填充第3个,可是如果下个石子是42 那么会覆盖第2个,那这样为什么还会有90个得分点?
s=2 t=3 l=100
3 10
1 3 5 2 3 2 2 2 2 2
0 1 2 3 4 5 6 7 8 9
想了想 会不会这种
2 3 2 然后新的石子刚好覆盖的是
2 3 3 那么紧接着的最小就会认为是3而不是2
所以把间隔调大些试试
把 i>a[p-1] + t 改为了 i>a[p-1] + 2*t
AC
#include <iostream.h>#define MAX_INT 999int delTa(int * a, int m, int k){int i=0;for (i=0; i<m; i++){if (k==a[i]) {return 1;}}if (i>=m) {return 0;}}int main(){ int i, j, l, s, t, m;int *a, *f;int beg;int p = 0;cin>>l>>s>>t>>m;a = new int[m];f = new int [t+1];//读入石子for (i=0; i<m; i++){cin>>a[i];}//冒泡排序石子for (i=1; i<m; i++){for (j=0; j<m-i; j++){if (a[j] > a[j+1]){a[j] = a[j] + a[j+1];a[j+1] = a[j] - a[j+1];a[j] = a[j] - a[j+1];}}}if (s==t){j = 0;for (i=0; i<m; i++){if (a[i] % s == 0){j++;}}cout<<j;return 0;}f[0] = 0;for (i=1; i<l+t; i++){int pos = i%(t+1);int del;//int del = delTa(a, m, i); if (i<a[p]) {if (p-1>=0 && i>a[p-1]+2*t){i = a[p]-1;continue;}else{del = 0;}//del = 0;}else if (i==a[p]){del = 1;}else {p = p+1<m ? p+1 : m-1;if (i==a[p]){del = 1;}else if (i>a[p-1]+2*t && i<a[p]){i = a[p]-1;continue;}else if (i>a[p]+2*t && i<l){i = l-1;continue;}else{del = 0;}}f[pos] = MAX_INT; for (j=s; j<=t; j++){int forePos = (i-j) % (t+1);if (i-j>=0 && f[pos]>f[forePos] + del){f[pos] = f[forePos] + del;}}//cout<<i<<':'<<f[i%(t+1)]<<' ';}j = MAX_INT;for (i=l; i<l+t; i++){if (j>f[i%(t+1)]){j = f[i%(t+1)];}}cout<<j;delete []a;delete []f;return 0;}
自己弄的复杂了,呵呵 后面再理理
- 过河
- 过河
- 过河
- 过河
- 过河
- 过河
- 过河
- 过河
- 过河
- 过河
- 过河
- 过河
- 过河卒
- 猴子过河
- 青蛙过河
- 小马过河
- 小马过河
- 过河问题
- 第四堂课后作业
- 22
- ipad mini导致的windows蓝屏问题及解决
- 为什么选择PHP
- 【html】<a href="#">、<a href="">
- 过河
- 腾讯马拉松编程大赛威威猫系列故事——吃鸡腿 java编程解法
- PHP FPM设置
- 递归
- 关于String类的String()、String(String original)两个构造器的讨论
- Hadoop Job Tuning
- fscanf rewind
- file_operation(文件操作)file(文件)inode(节点)三者比较
- 将exe文件剥离出swf文件