2013腾讯编程马拉松初赛第〇场

http://acm.hdu.edu.cn/listproblem.php?vol=36

1:小Q系列故事——屌丝的逆袭

思路:和省赛的那个题目类似,只要模拟一下就好...

View Code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))

#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define ll long long
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define lowbit(x)   (x)&(-x)
#define Read()  freopen("din.txt", "r", stdin)
#define Write() freopen("dout.txt", "w", stdout);
#define inf 0x7f7f7f7f

#define M 150
#define N 22
using namespace std;


int mat[N][N];
int ans[N][N];
int n,m;
int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};

int Abs(int x)
{
    if (x >= 0) return x;
    else return (-x);
}
int main()
{
    int i,j,k;
    while (~scanf("%d%d",&n,&m))
    {
        if (!n && !m) break;
        for (i = 0; i < n; ++i)
        {
            for (j = 0; j < m; ++j)
            {
                scanf("%d",&mat[i][j]);
            }
        }
        CL(ans,0);


        for (i = 0; i < n; ++i)
        {
            for (j = 0; j < m; ++j)
            {
                for (k = 0; k < 4; ++k)
                {
                    int ti = i + dir[k][0];
                    int tj = j + dir[k][1];
                    if (ti >= 0 && ti < n && tj >= 0 && tj < m)
                    {
                        if (mat[i][j]*mat[ti][tj] < 0)
                        ans[i][j] += Abs(mat[ti][tj]);
                        else ans[i][j] -= Abs(mat[ti][tj]);
                    }
                }
            }
        }
        int res = -inf;
        int row = 0, col = 0;
        for (i = 0; i < n; ++i)
        {
            for (j = 0; j < m; ++j)
            {
                    if (ans[i][j] > res)
                    {
                        res = ans[i][j];
                        row = i;
                        col = j;
                    }
                    else if (ans[i][j] == res && ((row > i) || (row == i && col > j)))
                    {
                        res = ans[i][j];
                        row = i;
                        col = j;
                    }
    //               printf("%d ",ans[i][j]);
            }
//           printf("\n");
        }
//        if (res == -inf) res = 0;
        printf("%d %d %d\n",row + 1,col + 1,res);
    }
    return 0;
}

 

2:小明系列故事——买年货

思路:DP ,才开始开了个三维的DP怎么调数据都不出来,后来一看不对。这样会出现重复选的可能。后来开成了四维,没有用滚动数组优化就可以过,不过时间还是很紧的。

dp[no][i][j][k] = max(dp[no][i][j][k],dp[no - 1][i - a][j][k] + val,dp[no - 1][i][j - b][k] + val,dp[no - 1][i][j][k - 1] + val,dp[no - 1][i][j][k]);

前几个还好想,就是在dp[no - 1][i][j][k]没处理好,就是对于这件物品,我可能不买。 no表示第几件物品,i表示金钱数,j表示积分,k表示可以免费领取的商品数。

View Code
//#pragma comment(linker,"/STACK:327680000,327680000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))

#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define ll __int64
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define lowbit(x)   (x)&(-x)
#define Read()  freopen("din.txt", "r", stdin)
#define Write() freopen("dout.txt", "w", stdout);


#define M 307
#define N 4100007
using namespace std;

struct node
{
    int a,b,val;
}nd[107];

int dp[107][107][107][6];

int n,v1,v2,k;

int DP(int no,int vi,int vj,int ki)
{

    if (no < 0 || vi < 0 || vj < 0 || ki < 0) return -1;

    if (dp[no][vi][vj][ki]) return dp[no][vi][vj][ki];
    int tmp;

    tmp = DP(no - 1,vi - nd[no].a,vj,ki);
    if (tmp != -1)
    {
        tmp += nd[no].val;
        dp[no][vi][vj][ki] = max(dp[no][vi][vj][ki],tmp);
    }

    tmp = DP(no - 1,vi,vj - nd[no].b,ki);
    if (tmp != -1)
    {
        tmp += nd[no].val;
        dp[no][vi][vj][ki] = max(dp[no][vi][vj][ki],tmp);
    }

    tmp = DP(no - 1,vi,vj,ki - 1);
    if (tmp != -1)
    {
        tmp += nd[no].val;
        dp[no][vi][vj][ki] = max(dp[no][vi][vj][ki],tmp);
    }

    tmp = DP(no - 1,vi,vj,ki);
    if (tmp != -1)
    dp[no][vi][vj][ki] = max(dp[no][vi][vj][ki],tmp);


    return dp[no][vi][vj][ki];
}
int main()
{
//    Read();
    int i;
    while (~scanf("%d%d%d%d",&n,&v1,&v2,&k))
    {
        for (i = 1; i <= n; ++i)
        {
            scanf("%d%d%d",&nd[i].a,&nd[i].b,&nd[i].val);
        }
        CL(dp,0);
        printf("%d\n",DP(n,v1,v2,k));
    }
    return 0;
}

 

优化到三维后相当于多维的01背包:

View Code
//#pragma comment(linker,"/STACK:327680000,327680000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))

#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define ll __int64
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define lowbit(x)   (x)&(-x)
#define Read()  freopen("din.txt", "r", stdin)
#define Write() freopen("dout.txt", "w", stdout);


#define M 307
#define N 4100007
using namespace std;

struct node
{
    int a,b,val;
}nd[107];

int dp[107][107][6];
int n,v1,v2,k;

int main()
{
//    Read();
    int i,j,ki,p;
    while (~scanf("%d%d%d%d",&n,&v1,&v2,&k))
    {
        CL(dp,0);
        for (i = 1; i <= n; ++i)
        {
            scanf("%d%d%d",&nd[i].a,&nd[i].b,&nd[i].val);
        }


        for (p = 1; p <= n; ++p)
        {
            for (i = v1; i >= 0; --i)
            {
                for (j = v2; j >= 0; --j)
                {
                    for (ki = k; ki >= 0; --ki)
                    {

                        int tmp = 0;
                        if (i - nd[p].a >= 0)
                        tmp = max(tmp,dp[i - nd[p].a][j][ki] + nd[p].val);

                        if (j - nd[p].b >= 0)
                        tmp = max(tmp,dp[i][j - nd[p].b][ki] + nd[p].val);

                        if (ki - 1 >= 0)
                        tmp = max(tmp,dp[i][j][ki - 1] + nd[p].val);

                        dp[i][j][ki] = max(dp[i][j][ki],tmp);
                    }
                }
            }
        }
        int ans = 0;
        for (i = 0; i <= v1; ++i)
        {
            for (j = 0; j <= v2; ++j)
            {
                for (ki = 0; ki <= k; ++ki)
                {
//                    printf("%d\n",dp[i][j][ki]);
                    ans = max(ans,dp[i][j][ki]);
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

 

3:吉哥系列故事——临时工计划

思路:DP ,按时间排序之后DP即可,dp[i]表示到第i个工作时,可获得最高的工资.dp[i] += max(dp[k])  k < i

View Code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))

#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define ll long long
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define lowbit(x)   (x)&(-x)
#define Read()  freopen("din.txt", "r", stdin)
#define Write() freopen("dout.txt", "w", stdout);
#define inf 0x7f7f7f7f

#define M 107
#define N 1007
using namespace std;

struct node
{
    int s,e;
    int val;
}nd[N];
int m,n;
int dp[N];

int cmp(node a,node b)
{
    if (a.s != b.s) return a.s < b.s;
    else return a.e < b.e;
}
int main()
{
//    Read();
    int i,j;
    int T;
    int s,e,val;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d%d",&m,&n);
        int tn = 0;
        for (i = 1; i <= n; ++i)
        {
            scanf("%d%d%d",&s,&e,&val);
            if (e >= 1 && e <= m && s >= 1 && s <= m)
            {
                nd[tn].s = s;
                nd[tn].e = e;
                nd[tn++].val = val;
            }
        }
        sort(nd,nd + tn,cmp);
//        for (i = 0; i < tn; ++i)
//        {
//            printf(">>%d %d %d\n",nd[i].s,nd[i].e,nd[i].val);
//        }
        CL(dp,0);
        for (i = 0; i < tn; ++i)
        {
            dp[i] = nd[i].val;
            int tmp = 0;
            for (j = 0; j < i; ++j)
            {
                if (nd[j].e < nd[i].s)
                {
                   tmp = max(tmp,dp[j]);
                }
            }
            dp[i] += tmp;
        }
        int ans = 0;
        for (i = 0; i < tn; ++i)
        {
            ans = max(ans,dp[i]);
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

4:湫湫系列故事——植树节

 思路:直接考虑可能会比较麻烦一点,我们考虑它的反面,只要我们选的其余两个人一个是他朋友,一个不是他朋友就满足了它的对立面,则一共有C(n,3)中组和,每一个i,存在对立面的可能数为a[i]*(an - 1 - a[i])中间会出现计算两次,顾要除以2;

View Code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))

#define ll __int64
#define inf 0x7f7f7f7f
#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)

#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define lowbit(x)   (x)&(-x)
#define Read()  freopen("din.txt", "r", stdin)
#define Write() freopen("dout.txt", "w", stdout);


#define N 1007
#define M 1007

const int mod = 1000000007;
using namespace std;
int a[N];

int main()
{
    int i,j;
    int T,n;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d",&n);
        for (i = 0; i < n; ++i)
        scanf("%d",&a[i]);

        int ans = 0;
        for (i = 0; i < n; ++i)
        {
            ans += (a[i]*(n - a[i] - 1));
        }
        double div = n*(n - 1)*(n - 2)/6;
        printf("%.3lf\n",1 - (1.0*ans)/(2*div));
    }
}

 

5:威威猫系列故事——篮球梦

思路:算出A要进攻多少场(m)之后,然后枚举得分分别为1,2,3的场数,就相当于吧这几场往m里面放,那么可能输为C(m,i)*C(m - i,j)*C(m - i - j,k);

View Code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))

#define ll __int64
#define inf 0x7f7f7f7f
#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)

#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define lowbit(x)   (x)&(-x)
#define Read()  freopen("din.txt", "r", stdin)
#define Write() freopen("dout.txt", "w", stdout);


#define N 1007
#define M 1007

const int mod = 1000000007;
using namespace std;
int a[N];

int main()
{
    int i,j;
    int T,n;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d",&n);
        for (i = 0; i < n; ++i)
        scanf("%d",&a[i]);

        int ans = 0;
        for (i = 0; i < n; ++i)
        {
            ans += (a[i]*(n - a[i] - 1));
        }
        double div = n*(n - 1)*(n - 2)/6;
        printf("%.3lf\n",1 - (1.0*ans)/(2*div));
    }
}

 

 

posted @ 2013-03-23 15:07  E_star  阅读(310)  评论(0编辑  收藏  举报