今天心情好,刷了两到ACM水题,思路很简单都在注释里,所以直接贴代码:

/**
 * @file 龟兔赛跑.cpp
 * @brief 龟兔赛跑 AC代码 (DP)
 * DP方程式: [到第i的充电站的最短时间] = [到最后一个冲了电的充电站的最短时间] + [那个充电站到第i个充电站的时间]
 *
 * @link http://acm.hdu.edu.cn/showproblem.php?pid=2059
 * @version 1.0
 * @author OWenT
 * @date 2013.07.15
 *
 * @history
 *
 *
 */

#include 
#include 
#include 
#include 
#include 
#include 

int pn[128];
double dp[128]; /** dp[i] 表示 到第i个充电站的最小时间(0为开始位置,n+1为终点) **/

double calc_charge_time(int dis, int v1, int v2, int c) {
    if (dis <= c)
        return 1.0 * dis / v1;

    return 1.0 * c / v1 + 1.0 * (dis - c) / v2;
}

int main(int argc, char* argv[]) {
    using namespace std;

    double eps = std::numeric_limits::epsilon();
    int l, n, c, t, vr, v1, v2;

    while(cin>> l) {
        cin >> n>> c>> t>> vr>> v1>> v2;

        pn[0] = 0; /** 0为起点 **/
        for (int i = 1; i <= n; ++ i) {
            cin>> pn[i];
        }
        pn[n + 1] = l; /** n+1为终点 **/

        memset(dp, 0, sizeof(dp));
        for(int i = 0; i <= n + 1; ++ i) {
            dp[i] = calc_charge_time(pn[i] - pn[0], v1, v2, c);
        }

        for(int i = 1; i <= n + 1; ++ i) {
            for(int j = 0; j < i; ++ j) {
                double tc = calc_charge_time(pn[i] - pn[j], v1, v2, c) + t + dp[j];
                dp[i] = std::min(tc, dp[i]);
            }
            
        }

        double rt = 1.0 * l / vr, tt = dp[n + 1];

        if (tt < rt)
            puts("What a pity rabbit!");
        else
            puts("Good job,rabbit!");
    }

    return 0;
}

/**
 * @file Zipper.cpp
 * @brief Zipper AC代码 (DP)
 * @link http://poj.org/problem?id=2192
 * DP方程式: [A串消耗个数i][B串消耗个数j] = min{[A串消耗个数i - 1][B串消耗个数j]|[A串消耗个数i][B串消耗个数j + 1]}
 * 以上分支选取条件是 A或B的新选用字符和C串新字符匹配
 *
 * @version 1.0
 * @author OWenT
 * @date 2013.07.15
 *
 * @history
 *
 *
 */

#include 
#include 
#include 
#include 
#include 


char strA[256], strB[256], strC[512];
int dp[256][256]; /** dp[i][j] = k 表示A消耗了i个字符,B消耗了j个字符,拼成的C串消耗了k个字符(其实就是i+j) **/

int main(int argc, char* argv[]) {
    using namespace std;
    int s, n;

    scanf("%d", &n);
    for( s = 0; s < n; ++ s) {
        scanf("%s %s %s", strA, strB, strC);
        int lenA = strlen(strA);
        int lenB = strlen(strB);
        int lenC = strlen(strC);
        bool bFlag = false;

        if ( lenC != lenA + lenB ) {
            printf("Data set %d: no\n", s + 1);
            continue;
        }

        memset(dp, 0, sizeof(dp));

        if (strA[0] == strC[0])
            dp[1][0] = 1;
        if (strB[0] == strC[0])
            dp[0][1] = 1;

        for (int i = 0; i <= lenA; ++ i) {
            for (int j = 0; j <= lenB; ++ j) {
                if (0 == dp[i][j])
                    continue;

                int ri = i + 1, rj = j + 1;

                if (strA[i] == strC[dp[i][j]]) {
                    dp[ri][j] = dp[i][j] + 1;
                    if (ri + j == lenC)
                        bFlag = true;
                }

                if (strB[j] == strC[dp[i][j]]) {
                    dp[i][rj] = dp[i][j] + 1;
                    if (i + rj == lenC)
                        bFlag = true;
                }
            }
        }

        printf("Data set %d: %s\n", s + 1, bFlag? "yes": "no");
    }

    return 0;
}

1.RangeMinimum、Maximum Query问题(计算单调区间内出现最多(少)的次数)

对元素的起点做离散化,再把离散化后的位置作为线段树的[l, r),记录次数为t.

对输入区间a, b:

如果(a = b){很好处理},

如果(a = b – 1){分别计算a、b的次数,取大(小)的一项},

题目链接:http://poj.org/problem?id=1474

写这题的目的是看完了zzy的论文,写了半平面交,验证一下正确性,结果发现我写的问题还是很多的。

题目大意是问能不能放一个摄像机,使得摄像机能看到整个多边形内部。

这题和1279和3130差不多,过了这题再去对付那两题就简单多了。

题目链接:http://acm.pku.edu.cn/JudgeOnline/problem?id=1986

这是一道并查集+树的题,采用Tarjan离线算法

首先BS一下出题的人,也太懒了吧,还要我们看1984题才知道输入

题目的意思是告诉一个节点数为40000的树,问我们两个节点间的距离。实际上就是找出公共父节点,Tarjan算法写挫了很容易TLE,我开始用Vector就写搓了,结果TLE,后来重写,自己写邻接表然后AC了。

题目链接:http://acm.pku.edu.cn/JudgeOnline/problem?id=2446

这是一道匹配题,把行数(r)和列数(c)按(r+c)%2分成两组,然后连边,做一次二分图匹配,可以直接用匈牙利算法

匹配数等于两组的元素个数则为YES,否则NO

代码如下:

#include 
#include 
#include 
#include 
#include 
using namespace std;

int py[4][2] = { {1, 0}, {-1, 0}, {0, 1}, {0, -1} };
/**
 * 最大二分图匹配
 * 最大二分图匹配 = 最小点覆盖
 * Base 1
 */
#define MAXM 1024 //行
#define MAXN 1024 //列
bool mat[MAXM][MAXN] = {false};
bool isMatchedR[MAXN] = {false};
int matchedR[MAXN];//调用前初始化: memset(matchedR, 0, sizeof(matchedR));

bool getLeftPath(bool matin[MAXM][MAXN], int pos, const int &n)
{
    int i;
    for(i = 1 ; i <= n ; i ++)
    {
        if(matin[pos][i] && !isMatchedR[i])
        {
            isMatchedR[i] = true;
            if(!matchedR[i] || getLeftPath(matin, matchedR[i], n))
            {
                matchedR[i] = pos;
                return true;
            }
        }
    }

    return false;
}
long GetMaxMacthNumber(bool matin[MAXM][MAXN], const int &m, const int &n)
{
    int i,ans = 0;
    for(i = 1 ; i <= m ; i ++)
    {
        memset(isMatchedR, false, sizeof(isMatchedR));
        if(getLeftPath(matin, i, n))
            ans++;
    }
    return ans;
}

bool mapbs[35][35];
int index[35][35];
int main()
{
    int m, n, k, i, j, r, c, tx, ty;
    scanf("%d %d %d", &n, &m, &k);
    memset(matchedR, 0, sizeof(matchedR));
    memset(mapbs, true, sizeof(mapbs));
    for(i = 0; i < k; i ++)
    {
        scanf("%d %d", &c, &r);
        mapbs[r][c] = false;
    }
    for(i = 0; i < 35; i ++)
        mapbs[0][i] = mapbs[i][0] = mapbs[n + 1][i] = mapbs[i][m + 1] = false;

    r = c = 0;
    for(i = 1; i <= n; i ++)
    {
        for(j = 1; j <= m; j ++)
        {
            if(mapbs[i][j])
            {
                if((i + j) % 2 == 0)
                    index[i][j] = ++ r;
                else
                    index[i][j] = ++ c;
            }
        }
    }
    for(i = 1; i <= n; i ++)
    {
        for(j = 1; j <= m; j ++)
        {
            if(mapbs[i][j] && (i + j) % 2 == 0)
            {
                for(k = 0; k < 4; k ++)
                {
                    tx = i + py[k][0];
                    ty = j + py[k][1];
                    if(mapbs[tx][ty])
                    {
                        mat[index[i][j]][index[tx][ty]] = true;
                    }
                }
            }
        }
    }

    if(r != c || GetMaxMacthNumber(mat, r, c) != r)
        printf("NO\n");
    else
        printf("YES\n");
    return 0;
}

http://www.cn210.com/onlinejudge/problemshow.php?pro_id=98

我们的OJ

Description

We say that a set 

$$S = {x1, x2, ..., xn}$$

is factor closed if for any xi ∈ S and any divisor d of xi we have d ∈ S. Let’s build a GCD matrix (S) = (sij), wheresij = GCD(xi, xj) - the greatest common divisor of xi and xj. Given the factor closed set S, find the value of the determinant:

Input

The input contains several test cases. Each test case starts with an integer n (0 < n < 1000), that stands for the cardinality of S.  The next line contains the numbers of S: x1, x2, …, xn.  It is known that each xi is an integer, 0 ≤ xi ≤ 2*109.  The input data set is correct and ends with an end of file.

题目链接:http://acm.pku.edu.cn/JudgeOnline/problem?id=3757

题目大意

第一行输入n,k,f表示从n个服务器里选k个,传输大小为f(以Mb为单位)的文件

接下来输入每个服务器的吞吐量,带宽和资源消耗(pi,bi,ci)

这道题是我专门为了了解和学习树状数组而写的

这题用树状数组记录翻转次数,然后mod一个2,也可以不断地取反

还要用到二维的树状数组.于是我专门写了个模板用

题目链接:http://acm.pku.edu.cn/JudgeOnline/problem?id=2155

题意大致是输入语句,Q表示要求输出A(x,y)是1还是0.C表示把(x1,y1)->(x2,y2)间的矩形中所有元素的1变成0,0变成1

题目链接:http://acm.pku.edu.cn/JudgeOnline/problem?id=1720

这题纯计算几何就搞定了,开始我写了个很长很长的代码,但是Wa掉,也不知道是代码那里有疏漏还是精度问题

看来我的搜索真的很烂,简单的搜索都搞定的这么痛苦

题目链接:http://acm.pku.edu.cn/JudgeOnline/problem?id=1724

题目大意是输入 拥有钱数,城市数,路的数量

然后输入格式是 起点,终点,路长,路费

3636 Nested Dolls

题目链接:[http://acm.pku.edu.cn/JudgeOnline/problem?id=3636

](http://acm.pku.edu.cn/JudgeOnline/problem?id=3636)好吧,这题我看了解题报告。而且解题报告有错误的。只考虑w递增,没考虑w值相等的情况。

我自己这里加进去了判断。主要是看解题报告后才知道数据这么弱,就按他的写了

大意是给出N个玩具,要求放k组,其中每组都是大玩偶套小玩偶。在w(宽)和h(高)都大于

题目链接:http://acm.pku.edu.cn/JudgeOnline/problem?id=3631

我讨厌这么长的题目

这题是模拟那个Hash算法,有点像我之前转载的那篇文章里提到的Hash

打造最快的Hash表(转) [以暴雪的游戏的Hash为例] 这里是用两个Hash函数算出两个Hash值h1和h2,如果h1位置已经被占用就检查h2位置,如果都被占用就把原来的替换掉再给原来的字符串重新计算映射。这样下去可能出现死循环。会出现死循环就输出

为什么我用线段数这么不灵活呢?

大概思路是线段数记录某牛之前的坐标小于这个牛的牛的坐标和和牛的个数

然后其他部分线性数组记录

OK,贴代码

#include 
#include 
#include 
#include 
using namespace std;

#define MAXN 20005
class cow
{
public:
    int v;
    int pos;
    cow(){};
    ~cow(){};
};

bool cmp(cow a,cow b)
{
    return a.v < b.v;
}
cow cw[MAXN];
long long belowXNT[MAXN];//树状数组,保存小于等于某坐标的牛的个数,计算时使用
long long belowXN[MAXN];//一般数组,保存小于等于某坐标和索引的牛的个数
long long velowXRT[MAXN];//树状数组,保存索引小于等于某的牛且坐标也小于它的牛的坐标之和,计算时使用
long long velowXR[MAXN];//一般数组,保存索引小于等于某的牛且坐标也小于它的牛的坐标之和
long long velowXRA[MAXN];//一般数组,保存小于等于某牛的坐标之和

int lowbit(int t)
{
    return t&(t^(t-1));
}
void setVal(int pos, int num, long long treeG[], int maxn)
{
    while (pos <= maxn)
    {
        treeG[pos] += num;
        pos += lowbit(pos);
    }
}
long long getSum(int pos, long long treeG[])
{
    long long sum = 0;
    while (pos > 0)
    {
        sum += treeG[pos];
        pos -= lowbit(pos);
    }
    return sum;
}



int main()
{
    int i,n;
    long long output = 0;
    memset(belowXN, 0, sizeof(belowXN));
    memset(belowXNT, 0, sizeof(belowXN));
    memset(velowXR, 0, sizeof(velowXR));
    memset(velowXRA, 0, sizeof(velowXRA));
    memset(velowXRT, 0, sizeof(velowXRT));
    scanf("%d",&n);
    for(i = 0 ; i < n ; i ++)
        scanf("%d %d", &cw[i].v, &cw[i].pos);

    sort(cw, cw + n, cmp);
    for(i = 0 ; i < n ; i ++)
    {
        velowXRA[i] = velowXRA[i - 1] + cw[i].pos;
        setVal(cw[i].pos, 1, belowXNT, MAXN);
        setVal(cw[i].pos, cw[i].pos, velowXRT, MAXN);
        velowXR[i] = getSum(cw[i].pos, velowXRT);
        belowXN[i] = getSum(cw[i].pos, belowXNT);
    }

    for(i = 1 ; i < n ; i ++)
        //output += cw[i].v * ((belowXN[i] - 1) * cw[i].pos - velowXR[i] + cw[i].pos + velowXRA[i] - velowXR[i] - (i - belowXN[i] + 1) * cw[i].pos);
        output += cw[i].v * ((belowXN[i] - i + belowXN[i] - 1 ) * cw[i].pos - 2 * velowXR[i] + velowXRA[i]);//这里是上面式子的简化版

    printf("%lld\n",output);
    return 0;
}