H题:
题目大意:
110米跨栏分为n个部分,每部分的速度均相同,可以有3种选择
- 快速,花费时间t1,花费精力f1
- 中速,花费时间t2,不花费精力
- 慢速,花费时间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;
}