zoukankan      html  css  js  c++  java
  • POJ杂题题解

    POJ1147

    根据最后一列,可以确定答案中0/1的个数,同样第一列也确定了,因为每次操作之后得到的矩阵都是排过序的,不妨考虑一下把最后一列移到第一列,这样可以得到最后一列与第一列排序的对应关系,然后根据这个对应关系就可以知道每一行经过排序会发生什么变化,这样不断递推就可以求出整个矩阵了。由于只需要第一行,输出即可。

    Code
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #include<ctime>
    #include<cstdlib>
    #include<set>
    #include<queue>
    #include<vector>
    #include<string>
    
    using namespace std;
    
    #define P system("pause");
    #define B printf("Break
    ");
    #define A(x) cout << #x << " " << (x) << endl;
    #define AA(x,y) cout << #x << " " << (x) << " " << #y << " " << (y) << endl;
    #define ll long long
    #define inf 1000000000
    #define linf 10000000000000000
    
    int read()
    {
        int x = 0,f = 1;
        char c = getchar();
        while(c < '0' || c > '9')
        {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9')
        {
            x = (x << 3) + (x << 1) + c - '0';
            c = getchar();
        }
        return f * x;
    }
    #define N 3010
    int f[N],nxt[N],ans[N];
    int main()
    {
        int n = read(),cnt = 0;
        for(int i = 1;i <= n;++i) f[i] = read();
        int tot = 0;
        for(int i = 1;i <= n;++i)
            if(!f[i]) nxt[++tot] = i;
        for(int i = 1;i <= n;++i)
            if(f[i]) nxt[++tot] = i;
        for(int i = 1,pos = nxt[1];i <= n;++i)
        {
            printf("%d ",f[pos]);
            pos = nxt[pos];
        }
        putchar('
    ');
    }
    
    

    POJ1163

    数字三角形,dp入门题。
    (f_{x,y} = max (f_{x+1,y},f_{x+1,y+1}) + a_{x,y})

    Code
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #include<ctime>
    #include<cstdlib>
    #include<set>
    #include<queue>
    #include<vector>
    #include<string>
    
    using namespace std;
    
    #define P system("pause");
    #define B printf("Break
    ");
    #define A(x) cout << #x << " " << (x) << endl;
    #define AA(x,y) cout << #x << " " << (x) << " " << #y << " " << (y) << endl;
    #define ll long long
    #define inf 1000000000
    #define linf 10000000000000000
    
    int read()
    {
        int x = 0,f = 1;
        char c = getchar();
        while(c < '0' || c > '9')
        {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9')
        {
            x = (x << 3) + (x << 1) + c - '0';
            c = getchar();
        }
        return f * x;
    }
    #define N 150
    int f[N][N],a[N][N],n;
    int dfs(int x,int y)
    {
        if(f[x][y]) return f[x][y];
        if(x == n) return f[n][y] = a[n][y];
        else return f[x][y] = max(dfs(x + 1,y),dfs(x + 1,y + 1)) + a[x][y];
    }
    int main()
    {
        n = read();
        for(int i = 1;i <= n;++i)
            for(int j = 1;j <= i;++j)
                a[i][j] = read();
        printf("%d
    ",dfs(1,1));
    }
    

    POJ1922

    理性分析一下,发现这个人一定会跟着骑得最快的人一块骑,因此只需统计出最先到达终点的人的时间即可。注意在0时刻之前出发的,要么一定会被这个人超过,要么永远追不上,所以不予考虑。

    Code
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #include<ctime>
    #include<cstdlib>
    #include<set>
    #include<queue>
    #include<vector>
    #include<string>
    
    using namespace std;
    
    #define P system("pause");
    #define B printf("Break
    ");
    #define A(x) cout << #x << " " << (x) << endl;
    #define AA(x,y) cout << #x << " " << (x) << " " << #y << " " << (y) << endl;
    #define ll long long
    #define inf 1000000000
    #define linf 10000000000000000
    
    int read()
    {
        int x = 0,f = 1;
        char c = getchar();
        while(c < '0' || c > '9')
        {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9')
        {
            x = (x << 3) + (x << 1) + c - '0';
            c = getchar();
        }
        return f * x;
    }
    int main()
    {
        int n;
        while(~scanf("%d",&n) && n)
        {
            double ans = inf;
            for(int i = 1;i <= n;++i)
            {
                double v,t,dt = inf;
                scanf("%lf%lf",&v,&t);
                if(t >= 0) dt = ceil(t + 4.5 / (v / 3600.0));
                ans = min(ans,dt);
            }
            printf("%d
    ",(int)ans);
        }
    }
    

    POJ2211

    题目大意:给定 (n), (k), 求给定排列在所有 (A_n^k) 种排列中的排名的字典序。

    这个题一看就跟组合数有关系,假设得到的排列是 (x_1,x_2,...,x_k) ,考虑所有比这个排列小的,按位考虑,显然所有第一个元素比 (x_1) 小的都符合,这些排列一共有 ((x_1-1)A_{n-1}^{k-1})个。然后继续往后考虑,到第 (i) 个元素,符合条件的是 ((x_i-1)A_{n-i}^{k-i}) ,但是这里的 (x_i) 有一点变化,如果前面已经考虑过比这个 (x_i) 小的元素了,那么就需要去重,具体方法见代码。

    Code
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #include<ctime>
    #include<cstdlib>
    #include<set>
    #include<queue>
    #include<vector>
    #include<string>
    
    using namespace std;
    
    #define P system("pause");
    #define B printf("Break
    ");
    #define A(x) cout << #x << " " << (x) << endl;
    #define AA(x,y) cout << #x << " " << (x) << " " << #y << " " << (y) << endl;
    #define ll long long
    #define inf 1000000000
    #define linf 10000000000000000
    
    ll read()
    {
        ll x = 0,f = 1;
        char c = getchar();
        while(c < '0' || c > '9')
        {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9')
        {
            x = (x << 3) + (x << 1) + c - '0';
            c = getchar();
        }
        return f * x;
    }
    #define N 20
    ll fac[N],x[N];
    ll a(ll n,ll m)
    {
        if(n < m) return 0;
        return fac[n] / fac[n - m];
    }
    int main()
    {
        ll T = read();fac[0] = 1;
        for(ll i = 1;i <= 12;++i) fac[i] = fac[i - 1] * i;//预处理阶乘
        for(ll j = 1;j <= T;++j)
        {
            ll n = read(),k = read(),ans = 0;
            for(ll i = 1;i <= k;++i) x[i] = read();
            for(ll i = 1;i <= k;++i)
            {
                ans += (x[i] - 1) * a(n - i,k - i);//按位计算
                for(int l = i + 1;l <= k;++l)
                    if(x[l] > x[i]) x[l]--;//这里去重
            }
            printf("Variace cislo %lld ma poradove cislo %lld.
    ",j,ans + 1);//诡异的输出格式
        }
    }
    
    

    POJ2215

    题目大意:给定一个矩形,内部每个点有权值,多次询问一个子矩形内部权值和。

    就是个水题啊,二维前缀和一下就搞定了。

    Code
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #include<ctime>
    #include<cstdlib>
    #include<set>
    #include<queue>
    #include<vector>
    #include<string>
    
    using namespace std;
    
    #define P system("pause");
    #define B printf("Break
    ");
    #define A(x) cout << #x << " " << (x) << endl;
    #define AA(x,y) cout << #x << " " << (x) << " " << #y << " " << (y) << endl;
    #define ll long long
    #define inf 1000000000
    #define linf 10000000000000000
    
    int read()
    {
        int x = 0,f = 1;
        char c = getchar();
        while(c < '0' || c > '9')
        {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9')
        {
            x = (x << 3) + (x << 1) + c - '0';
            c = getchar();
        }
        return f * x;
    }
    #define N 1010
    int a[N][N],sum[N][N];
    int main()
    {
        int T = read();
        while(T--)
        {
            memset(a,0,sizeof(a));
            memset(sum,0,sizeof(sum));
            int r = read(),s = read();
            for(int i = 1;i <= r;++i)
            {
                for(int j = 1;j <= s;++j)
                {
                    a[i][j] = read();
                    sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + a[i][j];
                }
            }
            int q = read();
            while(q--)
            {
                int r1 = read(),s1 = read(),r2 = read(),s2 = read();
                int ans = sum[r2][s2] - sum[r2][s1 - 1] - sum[r1 - 1][s2] + sum[r1 - 1][s1 - 1];
                printf("Absolutni hodnota pohodlnosti je %d bodu.
    ",ans);
            }
            puts("");
        }
    }
    
    

    POJ2229

    题目大意:求一个数 (n) 按照2的幂次拆分的方案数。

    看到方案数,又看到数据范围 (n leq 10^6) ,那就是dp了呗。

    定义 (dp_i) 为拆分数 (i) 的方案数,它可以从 (i-1,i-2,...,i-2^k) 转移过来。故方程显然:

    [dp_i = sum_k^{log_2 i}dp_{i-2^k} ]

    再仔细一看,这不就是完全背包的形式吗,有 (log_2n) 件物品,求装入体积为 (n) 的背包的方案总数。
    (O(nlog n)) 复杂度。

    还有一种打表找规律做到 (O(n)) 的方法,当 (i) 为奇数时,它只能通过 (i-1+2^0) 得到,比如:(5) 只能通过 (4+2^0) 得到,当 (i) 为偶数时,它既可以通过 (i-1+2^0) ,又可以通过 (dfrac{i}{2}*2) 得到,比如:(6) 可以通过 (5+2^0) 得到,也可以通过 (3*2) 得到。

    代码是完全背包做法。

    Code
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #include<ctime>
    #include<cstdlib>
    #include<set>
    #include<queue>
    #include<vector>
    #include<string>
    
    using namespace std;
    
    #define P system("pause");
    #define B printf("Break
    ");
    #define A(x) cout << #x << " " << (x) << endl;
    #define AA(x,y) cout << #x << " " << (x) << " " << #y << " " << (y) << endl;
    #define ll long long
    #define inf 1000000000
    #define linf 10000000000000000
    
    int read()
    {
        int x = 0,f = 1;
        char c = getchar();
        while(c < '0' || c > '9')
        {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9')
        {
            x = (x << 3) + (x << 1) + c - '0';
            c = getchar();
        }
        return f * x;
    }
    #define N 1000100
    #define mod 1000000000
    int dp[N],a[30];
    int main()
    {
        int n = read();
        int tot = 1,cnt = 0;
        while(tot <= n) a[++cnt] = tot,tot <<= 1;
        dp[0] = 1;
        for(int i = 1;i <= cnt;++i)
        {
            for(int j = a[i];j <= n;++j)
            {
                dp[j] = (dp[j] + dp[j - a[i]]) % mod;
            }
        }
        printf("%d
    ",dp[n]);
    }
    
    

    POJ2232

    什么叫“随机”啊,那就是可以随便操作的意思。如果三种手势都有,我们完全可以直接操作一下让每个人都获胜,因为保证了不存在平局嘛。而如果只有两种手势,那就只能是赢的那种手势的人才能获胜。一种手势比较显然,都可以获胜。

    Code
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #include<ctime>
    #include<cstdlib>
    #include<set>
    #include<queue>
    #include<vector>
    #include<string>
    
    using namespace std;
    
    #define P system("pause");
    #define B printf("Break
    ");
    #define A(x) cout << #x << " " << (x) << endl;
    #define AA(x,y) cout << #x << " " << (x) << " " << #y << " " << (y) << endl;
    #define ll long long
    #define inf 1000000000
    #define linf 10000000000000000
    
    int read()
    {
        int x = 0,f = 1;
        char c = getchar();
        while(c < '0' || c > '9')
        {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9')
        {
            x = (x << 3) + (x << 1) + c - '0';
            c = getchar();
        }
        return f * x;
    }
    int main()
    {
        int n;
        while(scanf("%d 
    ",&n) != EOF)
        {
            int sums = 0,sumc = 0,sumf = 0;
            string s;
            getline(cin,s);
            for(int i = 0;i < s.size();++i)
            {
                if(s[i] == 'C') sumc++;
                if(s[i] == 'S') sums++;
                if(s[i] == 'F') sumf++;
            }
            if((sumf != 0 && sums != 0 && sumc != 0) || (sumf == n || sums == n || sumc == n))
            {
                printf("%d
    ",n);
                continue;
            }
            else
            {
                if(sumf == 0 && sums != 0 && sumc != 0) printf("%d
    ",sumc);
                else if(sumf != 0 && sums == 0 && sumc != 0) printf("%d
    ",sumf);
                else if(sumf != 0 && sums != 0 && sumc == 0) printf("%d
    ",sums);
            }
        }
    }
    
    

    POJ2234

    Nim游戏模板题,若每堆数量异或和为0,则先手必败,否则先手必胜。

    Code
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #include<ctime>
    #include<cstdlib>
    #include<set>
    #include<queue>
    #include<vector>
    #include<string>
    
    using namespace std;
    
    #define P system("pause");
    #define B printf("Break
    ");
    #define A(x) cout << #x << " " << (x) << endl;
    #define AA(x,y) cout << #x << " " << (x) << " " << #y << " " << (y) << endl;
    #define ll long long
    #define inf 1000000000
    #define linf 10000000000000000
    
    int read()
    {
        int x = 0,f = 1;
        char c = getchar();
        while(c < '0' || c > '9')
        {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9')
        {
            x = (x << 3) + (x << 1) + c - '0';
            c = getchar();
        }
        return f * x;
    }
    int n;
    int main()
    {
        while(scanf("%d",&n) != EOF)
        {
            int ans = 0;
            for(int i = 1;i <= n;++i) ans ^= read();
            puts(ans ? "Yes" : "No");
        }
    }
    
    

    POJ2242

    Code
    
    

    POJ2245

    Code
    
    

    POJ2262

    Code
    
    

    POJ2301

    Code
    
    

    POJ2309

    Code
    
    

    POJ2313

    Code
    
    

    POJ2334

    Code
    
    

    POJ2346

    Code
    
    

    POJ2348

    Code
    
    

    POJ2350

    Code
    
    

    POJ2352

    Code
    
    

    POJ2381

    Code
    
    

    POJ2405

    Code
    
    

    POJ2406

    Code
    
    
  • 相关阅读:
    CC++ 文件操作
    loadrunner之Paramater在负载测试中的数据生成规则
    loadrunner关联及web_reg_save_param方法浅析
    mysql union 与 union all 语法及用法
    sql 语句中as的用法和作用
    数据库主从复制和读写分离
    《剑指offer》算法题第十二天
    《剑指offer》算法题第十一天
    《剑指offer》算法题第十天
    《剑指offer》算法题第九天
  • 原文地址:https://www.cnblogs.com/lijilai-oi/p/12759295.html
Copyright © 2011-2022 走看看