A题想法很简单,就是依次加入一种牌,去判断一下是否可行。但有细节的地方值得注意,一个是不能加已经有4张的牌,还有特殊处理"Kokushi Muso"的时候,注意这种情况,1m,9m,1p,9p,1s,9s,1c,2c,3c,4c,5c,6c,6c 答案可以是7c。
B题枚举一下因子,然后进制转换就ok了。
C题,不算难的dp,因为最初思考有偏差,导致纠结很久。。。
状态dp[i][p1][p2]表示i之前的已经对照成功,s1[i]=p1&&s1[i+1]=p2时需要的最小steps;
状态转移就成了dp[i][][]->dp[i+1][][], 那么s1[i]=p1必须调整到s2[i],方向有up和down,对应steps是固定的,并且满足steps(i)>=steps(i+1)>=steps(i+2) ,我们就可以通过对所有情况的枚举来一次更新状态;最后找一下dp[l][][]中的最优值。
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
char s1[1100],s2[1100];
int dp[1100][11][11];
int l;
int min(int a,int b)
{
if (a==-1) return b;
if (a<b) return a;
return b;
}
int main()
{
// freopen("in.txt","r",stdin);
while (~scanf("%s%s",s1,s2))
{
l=strlen(s1);
memset(dp,-1,sizeof(dp));
dp[0][s1[0]-'0'][s1[1]-'0']=0;
s1[l]=s1[l+1]=s2[l]=s2[l+1]='0';
for (int i=0;i<l;i++)
{
int p3= s1[i+2]-'0';
for (int p1=0;p1<=9;p1++)
for (int p2=0;p2<=9;p2++)
if (dp[i][p1][p2]!=-1)
{
int up,down;
if (p1>s2[i]-'0')
{
up=10-p1+s2[i]-'0';
down=p1-(s2[i]-'0');
}
else
{
up=s2[i]-'0'-p1;
down=p1+10-(s2[i]-'0');
}
for (int j=0;j<=up;j++)
for (int k=0;k<=j;k++)
dp[i+1][(p2+j)%10][(p3+k)%10]=
min(dp[i+1][(p2+j)%10][(p3+k)%10],dp[i][p1][p2]+up);
for (int j=0;j<=down;j++)
for (int k=0;k<=j;k++)
dp[i+1][(p2-j+10)%10][(p3-k+10)%10]=
min(dp[i+1][(p2-j+10)%10][(p3-k+10)%10],dp[i][p1][p2]+down);
}
}
int ans=100000;
for (int p1=0;p1<=9;p1++)
for (int p2=0;p2<=9;p2++)
ans=min(dp[l][p1][p2],ans);
printf("%d\n",ans);
}
return 0;
}
E题表示我起初写的也很乱七八糟,由Building an oil station in city i will cost 2i-1 MMMB.可以想到一个贪心策略,就是在建i号点的时候,如果我们把小于i的点都建起来可以不建i号点的话,就选择不建i号点,因为
2i-1>2i-2 +...+1;
那就从最大的点依次来判断是否可以不建,假设这个点不建还可以满足条件,就要符合1.所有要建加油站的点可以生成一棵1号点为根节点,每条路径<=d的树;
2.所有不建加油站的点都可以找到一个建加油站的点满足两点之间距离<=d/2;
如果两个条件都满足,这个点就选择不建,有一个条件不满足,就必须要在该点建加油站。
注意判断一下所有点都建加油站是否满足条件的情况。
H题是高中概率,水题。