H题:
题目大意:
110米跨栏分为n个部分,每部分的速度均相同,可以有3种选择

  1. 快速,花费时间t1,花费精力f1
  2. 中速,花费时间t2,不花费精力
  3. 慢速,花费时间t3,恢复精力f2(精力有上限m)
    开始时精力为m,求跑完110米的最短时间

分析:
DP是很明显的,f[i][j]中i表示路段,j表示精力,那么完全可以由上一个路段推知当前路段的状态。不过这个题没有给出数据范围,所以数组开大了,由此我发现了一种新的错误Segmentation Fault,QAQ

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<cmath>
#include<map>
#include<vector>
using namespace std;

struct node
{
    int t1,t2,t3,f1,f2;
}a[20000];

int T,n,m,ans;
int f[500][500];   //数组不要开太大QAQ

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        memset(f,0x3f,sizeof(f));
        for(int i = 1;i <= n; ++i)
            scanf("%d%d%d%d%d",&a[i].t1,&a[i].t2,&a[i].t3,&a[i].f1,&a[i].f2);
        for(int i = 0;i <= m; ++i)f[0][i] = 0;
        for(int i = 1;i <= n; ++i)
        {
            for(int j = 0; j <= m; ++j)
            {
                f[i][j] = min(f[i - 1][j] + a[i].t2,f[i][j]);    //中速
                if(j >= a[i].f1) 
                    f[i][j - a[i].f1] = min(f[i - 1][j] + a[i].t1,f[i][j - a[i].f1]);   //快速
                if(j + a[i].f2 > m) 
                    f[i][m] = min(f[i][m],f[i - 1][j] + a[i].t3);
                else 
                    f[i][j + a[i].f2] = min(f[i][j + a[i].f2],f[i - 1][j] + a[i].t3);  //慢速,注意精力有上限
            }
        }
        ans = 0x3f3f3f3f;
        for(int i = 0;i <= m; ++i)
           if(f[n][i])  ans = min(ans , f[n][i]);
        printf("%d\n",ans);
    }
    return 0;
}

K题:
题目大意:
有一个由‘B’‘J’‘H’‘Y’‘N’构成的矩阵,问有多少个矩阵四个角的字母都相等

分析:
因为250的n,m,刚开始怎么考虑也离不了4层循环的复杂度
可以先枚举两行,对于这两行,确定一个字母,找出这两行的对应元素纵坐标相等时是否都与这个字母相等,相等s+1,最后这两行可以构成的以这个字母为四角的数目=C(s,2)
这样就成功的把一层250的循环变成了5的循环,复杂度是可以接受的

#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<cmath>
#include<vector>
using namespace std;

char a[300][300];
int T,n,m,s;

int main()
{
    scanf("%d",&T);
    char c[] = {'B','J','H','Y','N'};
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i = 0;i < n; ++i) scanf("%s",a[i]);
        int res = 0;
        for(int i = 0;i < n; ++i)
            for(int j = i + 1;j < n; ++j)   //枚举两行
            {
                for(int k = 0;k < 5; ++k)   //确定某一个字母
                    {
                        s = 0;
                        for(int l = 0;l < m; ++l)
                            if(a[i][l] == c[k] && a[i][l] == a[j][l]) s++;   
                        res += (s - 1) * s / 2;
                    }

            }
        printf("%d\n",res);
    }
    return 0;
}