01背包问题基础

编 写: zhangyue
时 间: 2016-12-27
说 明: 利用背包问题解决红包使用问题

一 01背包问题

    01背包问题是指在一个容量大小固定为M的背包中,装入体积和价值不同的宝石,怎么选择才能在背包中得到最大的价值。

二 动态规划

动态规划是指
        通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以一种循环的方式去解决。
        通常基于一个递推公式和一个或多个初始状态,当前子问题的解由上一个子问题的解推出。
        有一类活动的过程,由于它的特殊性,可将过程分成若干个互相联系的阶段,在它的每一阶段都需要作出决策,从而使整个过程达到最        好的活动效果。当然,各个阶段决策的选取不是任意确定的,它依赖于当前面临的状态,又影响以后的发展,当各个阶段决策确定后,就组成一个决策序列,因而也就确定了整个过程的一条活动路线
        
        状态转移方程:
            d(N,M) = max(d(N-1,M), d(N-1, M-weight(i)) + value(i));
            d(N,M) 有容量为M的背包,有N个宝石
            d(N-1,M) 当前的宝石不放入背包,所能获取的最大价值
            d(N-1, M-weight(i)) + value(i) 当前宝石放入背包,所能够获取的最大价值

三 代码

function getResult($bagItems, $bagSize) {
        var result = array();
        //生成状态数组
        foreach ($i = 0; $i < $bagSize; $i ++) {
            foreach ($j = 0; $j < count($bagItems); $j ++) {
                if ($bagItems[$j]['weight'] > $i) {
                    //当前重量大于当前背包总重量
                    if (j != 0) {
                        $result[$j][$i] = $result[$j-1][$i];
                    } else {
                        //第一个元素 $j-1不存在,不存在前一个状态
                        $result[$j][$i] = 0;
                    }
                } else {
                    //当前重量小于背包,可以放入背包
                    if ($j != 0 ) {
                        $tmp_value = $result[$j-1][$i - $bagItems[$j]['weight']] + $bagItems[$j]['weight'];
                        $result[$j][$i] = max($result[$j-1][$i], $tmp_value);
                    } else {
                        //第一个元素 $j-1不存在,不存在前一个状态
                        $result[$j][$i] = $bagItems[$j]['weight'];
                    }
                }
            }
        }

        //根据得到的状态得到所选的数组
        $return  = array();//存储放回的组合
        $cur_size = $bagSize;//当前红包容量
        for ($n = count($bagItems); $n >= 0 ; $n--) {
            if ($cur_size == 0) {
                break;
            } 

            if ($n == 0 && $bagItems[$n]['weight'] < $cur_size) {
                $return[] = $bagItems[$n]['id'];
                break;
            }

            if ($bagItems[$n][$cur_size] - $bagItems[$n-1][$cur_size - $bagItems[$n]['weight']] == $bagItems[$n]['weight']) {
                //判断当前的这个商品是不是在最优解里,如果不在则不放入
                $return[] = $bagItems[$n]['id'];
                $cur_size = $cur_size - $bagItems[$n]['weight'];
            }
        }

        //得到结果
        return $return;

    }

四 递推表格

函数得到的递推表格和最终最优结果:
体积 价值 0 1 2 3 4 5 6 7 8 9 10 11
4 4 0 0 0 0 4 4 4 4 4 4 4 4
5 5 0 0 0 0 4 5 5 5 5 9 9 9
6 6 0 0 0 0 4 5 6 6 6 9 10 11
解释: 1 表格是从上到下,即4-6,从左到右,即0-11生成的 2 第一行的意思:代表在0-11的背包容量下,只有一个体积为4价值为4的宝石时,所能获得最大容量 3 第二行的意思:代表在0-11的背包容量下,有一个体积为4价值为4和体积为5价值为5的两块宝石时,所能获得最大容量 4 第三行的意思:代表在0-11的背包容量下,有一个体积为4价值为4,体积为5价值为5,体积为6价值为6的三块宝石时,所能获得最大容量 5 最终结果:[6,11] = 11 这个最优解。

五 红包问题

使用红包时,只需要将价值和体积都类比于红包的金额即可,这样可以选出最后得到的红包使用组合。
存在问题:
    1 红包会涉及小数的问题,红包现在只保留两位小数,最简单的方法是给红包*100,这样会增加递推数组的大小,增加空间复杂度
    2 红包还存在过期时间,可考虑如何加上过期时间这一条件
    3 由于红包价格和体积是同一个值,可考虑简化算法

用户系统演进

用户系统演进.ppt

编   写:袁 亮
时   间:2016-12-21
说   明:用户系统演进

一、用户系统限制因素
    1、使用域名
        单个域名
        多个域名
    2、使用系统是单服务器还是多服务器
    3、使用域名是否属于同一个域名的不同子域名
    4、系统访问环境
        PC浏览器
        是否兼容IE浏览器
        是否兼容手机浏览器
    5、用户数据库是否唯一
        单一用户数据库
        多个用户数据库
        
二、单用户中心,单域名
    1、条件限制
        1.1 单个域名
        1.2 单一用户数据库
    2、实现方案
        2.1 session
            磁盘IO 
            多服务器session共享
        2.2 cookie
            域名,端口,路径,cookie名
            数据签名
            大小限制
            敏感信息
    3、其他
        3.1 可以有多种登陆方式
        3.2 可以接入很多种第三方登陆
        
三、单用户中心,单个根域名
    1、条件限制
        1.1 单个用户数据库
        1.2 多个域名同属于某个根域名
    2、实现方案
        2.1 cookie共享 (育儿网)
            a. cookie设置在根域名
            b. 所有子域名都可以正常读取并验证签名
            c. 不可扩展,安全性无保障
        2.2 token形式 (共享session机制的变种)
            a. cookie设置在根域名
            b. 子域名读取到cookie之后,调用用户中心接口获取用户数据
            c. 将用户数据写入当前域名下
            
四、单用户中心,多个根域名
    1、条件限制
        1.1 单个用户数据库
    2、实现方案
        2.1 单点登陆 jsonp方式跨域 (淘宝)
            a. 统一的登陆,查收ticket
            b. jsonp方式将ticket循环传递给所有业务
            c. 业务域名根据ticket获取用户信息设置登陆
            d. 退出同样方式处理
            缺点:
                ios下,浏览器默认禁止第三方域名cookie设置,直接歇菜
        2.2 单点登陆 cas方式 (新浪)
            a. 通过jsonp+ajax+iframe的方式,在各个子域名框用户中心登陆
            b. 
            缺点:手机浏览器对iframe支持的很差
        2.3 服务端ticket形式,jsonp形式单点登录的变种
        
五、多用户中心
    1、条件限制
        无
    2、实现方案
        2.1 单域名或者多根域名跨域同三和四
    3、额外增加处理
        3.1 统一跳转地址
        3.2 用户聚合统一
        3.3 平台信息维护
        3.4 vtoken登录

linux定时任务的设置 crontab

一、基本使用
#分 时 日 月 周
* * * * * /home/blue/do/rsyncfile.sh

二、语法
crontab [-u username] [-l|-e|-r]
选项与参数:
-u :只有 root 才能进行这个任务,亦即帮其他使用者创建/移除 crontab 工作排程;
-e :编辑 crontab 的工作内容
-l :查阅 crontab 的工作内容 (备份)
-r :移除所有的 crontab 的工作内容,若仅要移除一项,请用 -e 去编辑

三、crontab的限制
/etc/cron.allow:将可以使用 crontab 的帐号写入其中,若不在这个文件内的使用者则不可使用 crontab;
/etc/cron.deny:将不可以使用 crontab 的帐号写入其中,若未记录到这个文件当中的使用者,就可以使用 crontab 。

以优先顺序来说, /etc/cron.allow 比 /etc/cron.deny 要优先, 而判断上面,这两个文件只选择一个来限制而已,因此,建议你只要保留一个即可, 免得影响自己在配置上面的判断!一般来说,系统默认是保留 /etc/cron.deny ,你可以将不想让他运行 crontab 的那个使用者写入 /etc/cron.deny 当中,一个帐号一行!
crontab3

四、crontab的原理
crond服务的最低侦测限制是分钟,所以cron 会每分钟去读取一次 /etc/crontab 与 /var/spool/cron 里面的数据内容,因此,只要你编辑完 /etc/crontab 这个文件,并且将他储存之后,那么 cron 的配置就自动的会来运行了!

执行脚本的用户:/var/spool/cron/
执行记录:/var/log/cron
crontab2

五、crontab 的格式

代表意义 分钟 小时 日期(天) 月份 周 命令
数字范围 0-59 0-23 1-31 1-12 0-7 执行的命令
周的数字为 0 或 7 时,都代表『星期天』的意思!

辅助字符

特殊字符 代表意义
*(星号) 任何时刻
,(逗号) 代表分隔时段
-(减号) 代表一段时间范围内
/n(斜线) 代表每隔n单位间隔

六、周与日月
周和日月不是 并 的关系,而是 或 的关系。

你可以分别以周或者是日月为单位作为循环,但你不可使用「几月几号且为星期几」的模式工作。
30 12 11 11 5 root echo "just test" <==这是错误的写法
本来你以为十一月十一号且为星期五才会进行这项工作,无奈的是,系统可能会判定每个星期五作一次,或每年的 11月 11 号分别进行。

测试:(12月8号为星期4)
25 18 08 12 4 (echo "just test1" >> /tmp/test.txt ) //执行一次
25 18 07 12 4 (echo "just test2" >> /tmp/test.txt ) //执行一次
25 18 08 12 5 (echo "just test3" >> /tmp/test.txt) //执行一次

七、& 后台执行命令
1. command & : 后台运行,你关掉终端会停止运行
2. nohup command & : 后台运行,你关掉终端也会继续运行

参考:http://www.cnblogs.com/lwm-1988/archive/2011/08/20/2147299.html

八、2>&1 含义
先看一个例子:
0 2 * * * echo "just test" >> /tmp/test.txt 2>&1 &
这句话的意思就是在后台执行这条命令,并将错误输出2重定向到标准输出1,然后将标准输出1全部放到/dev/null 文件,也就是清空。

注释:
数字的含义:
0表示 键盘输入
1表示 标准输出
2表示 错误输出
>>是追加内容
> 是覆盖原有内容

示例:
0 2 * * * sh /tmp/test.sh 1>/tmp/out.file &
0 2 * * * sh /tmp/test.sh 2>/tmp/out.file &
0 2 * * * sh /tmp/test.sh 2>/tmp/out.file 2>&1 &
1、将tesh.sh 命令输出重定向到out.file, 即输出内容不打印到屏幕上,而是输出到out.file文件中。
2、2>&1 是将错误输出重定向到标准输出。 然后将标准输入重定向到文件out.file。
3、&1 表示的是文件描述1,表示标准输出,如果这里少了&就成了数字1,就表示重定向到文件1。
4 、& :后台执行

测试:
ls 2>1 : 不会报没有2文件的错误,但会输出一个空的文件1;
ls xxx 2>1: 没有xxx这个文件的错误输出到了1中;
ls xxx 2>&1: 不会生成1这个文件了,不过错误跑到标准输出了;
ls xxx >out.txt 2>&1 == ls xxx 1>out.txt 2>&1: 因为重定向符号>默认是1,这句就把错误输出和标准输出都传到out.txt 文件中。

九、注意点:2>&1写在后面的原因
格式:command > file 2>&1 == command 1> file 2>&1
首先是command > file将标准输出重定向到file中, 2>&1 是标准错误拷贝了标准输出,也就是同样被重定向到file中,最终结果就是标准输出和错误都被重定向到file中。

如果改成: command 2>&1 >file
2>&1 标准错误拷贝了标准输出的行为,但此时标准输出还是在终端。>file 后输出才被重定向到file,但错误输出仍然保持在终端。
crontab1