2013年8月九度Online Judge程序猿求职及面试月赛

题目1 棋盘寻宝

两种思路:(1)二维的动态规划(解题报告)(2)深搜(自己).动态规划只需要0ms,而深搜却需要50ms。

动态规划需要满足的条件:点击打开链接

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

int map[8][8], dp[8][8];
int main()
{
    int i, j;
    //freopen("/home/lsy/Desktop/2.txt", "r", stdin);
    while(scanf("%d", &map[0][0]) != EOF) {
        for(i=0; i<8; i++) {
            for(j=0; j<8; j++) {
                dp[i][j] = 0;
                if(i==0 && j==0) continue;
                scanf("%d", &map[i][j]);
            }
        }
        for(i=0; i<8; i++) {
            for(j=0; j<8; j++) {
                if(i==0 && j==0) {dp[i][j] = map[i][j];continue;}
                if(i==0) dp[i][j] = dp[i][j-1] + map[i][j];
                else if(j==0) dp[i][j] = dp[i-1][j] + map[i][j];
                else dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + map[i][j];
            }
        }
        printf("%d\n", dp[7][7]);
    }
    return 0;
}
题目4 棋盘寻宝扩展

思路:深搜+剪枝

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
int map[8][8];
int visit[8][8];
int go[2][2] = { {0, 1}, {1, 0} };
int T, maxL = 0;
void dfs(int x, int y, int num) {
    if(num > T) return;
    if(x == 7 && y == 7) {
        if(maxL < num) {
            maxL = num;
            //printf("maxL = %d\n", maxL);
        }
        return;
    }
    int i;
    for(i=0; i<2; i++) {
        int nx = x + go[i][0];
        int ny = y + go[i][1];
        if(nx<0 || nx >7 || ny<0 || ny>7) continue;
        if(visit[nx][ny] == 1) continue;
        visit[nx][ny] = 1;
        dfs(nx, ny, num+map[nx][ny]);
        visit[nx][ny] = 0;
    }
}
int main()
{
    int i, j;
    //freopen("/home/lsy/Desktop/2.txt", "r", stdin);
    while(scanf("%d", &T) != EOF) {
        maxL = 0;
        for(i=0; i<8; i++)
            for(j=0; j<8; j++) {
                visit[i][j] = 0;
                scanf("%d", &map[i][j]);
            }
        visit[0][0] = 1;
        dfs(0, 0, map[0][0]);
        if(maxL == 0) printf("-1\n");
        else printf("%d\n", maxL);
    }
    return 0;
}

题目2 最长不重复子串
思路:和求最大子串的和一样。无非是加了个限制条件。O(n)的算法。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 10010;
int hash[27][2];
char str[MAXN];
int main()
{
    int maxL, len, i, pos;
    while(scanf("%s", str) != EOF) {
        maxL = len = 0;
        memset(hash, 0, sizeof(hash));
        pos = 1;
        for(i=0; str[i]; i++) {
            if(1 == hash[str[i]-'a'][0]) {
                if(pos < hash[str[i]-'a'][1]) pos = hash[str[i]-'a'][1];
                len =i - pos;
                len++;
                hash[str[i]-'a'][1] = i+1;
            } else {
                len ++;
                hash[str[i]-'a'][0] = 1;
                hash[str[i]-'a'][1] = i+1;
            }
            //printf("len = %d\n", len);
            if(maxL < len) maxL = len;
        }
        //printf("len = %d\n", len);
        printf("%d\n", maxL);
    }
    return 0;
}

题目3 货币面值
思路:当时用的深搜,果断TLE。后来看了解题报告,才知道是01背包问题。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 6000;
int A[110], dp[MAXN];
int main() {
    int i, j, m, n;
    freopen("/home/lsy/Desktop/2.txt", "r", stdin);
    while(scanf("%d", &n) != EOF) {
        m = 0;
        memset(dp, 0, sizeof(dp));
        for(i=0; i<n; i++) {
            scanf("%d", &A[i]);
            m += A[i];
        }
        dp[0] = 1;
        for(i=0; i<n; i++) {
            //dp[A[i]] = 1;//这是值得注意的地方,想想???
            for(j=m; j>=A[i]; j--) {//逆序。为什么不是顺序??
                if(dp[j-A[i]]) dp[j] = 1;
            }
        }
        for(i=0; i<m+2; i++)
            if(dp[i] == 0) break;
        printf("%d\n", i);
    }
    return 0;
}

总结:本次题目相对来说比较简单。都有思路。对7月份的,有一道题(Manacher算法,求最长回文串)完全没听说过。看着这么多AK的,看来自己应该加把劲了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值