注:此博客记录一些蓝桥杯水题,但是自己第一时间没想出来,但暴力的题目
蓝桥杯2015初赛牌型种数题目链接
题目思路
我本以为是组合数学,但是发现组合数学好像写不出,去看了一下答案居然是13重for或暴力dfs,不过dp也可以求解
dfs
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
int ans;
void dfs(int cnt,int k){
if(cnt==13){
ans++;
}
if(cnt>=13||k>=13){
return ;
}
for(int i=0;i<=4;i++){
dfs(cnt+i,k+1);
}
}
int main(){
dfs(0,0);
printf("%d\n",ans);
return 0;
}
dp
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
LL dp[14][14]; // dp[i][j]: 当前到第i张牌,总共有j张牌时的解的个数
int main() {
dp[1][0] = dp[1][1] = dp[1][2] = dp[1][3] = dp[1][4] = 1;
for (int i = 2; i <= 13; i++) {
for (int k = 0; k <= 13; k++) {
if (k - 4 >= 0) dp[i][k] += dp[i-1][k-4];
if (k - 3 >= 0) dp[i][k] += dp[i-1][k-3];
if (k - 2 >= 0) dp[i][k] += dp[i-1][k-2];
if (k - 1 >= 0) dp[i][k] += dp[i-1][k-1];
dp[i][k] += dp[i-1][k];
}
}
cout << dp[13][13] << endl;
return 0;
}
蓝桥杯2015初赛生命之树题目链接
题目思路
本来以为是树的直径模板题,发现不是,因为这个是可以分叉的链,而树的直径是要求一条不能分叉的链。但其实这样更加简单,要分类讨论一下,自己原先没有分类讨论就wa了,树形dp一下就行了
代码
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=1e5+5;
typedef long long ll;
int n,u,v,a[maxn],head[maxn],cnt;
ll dp[2][maxn];
struct node{
int to,next;
}e[maxn<<1];
void add(int u,int v){
e[++cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt;
}
void dfs(int son,int fa){
dp[1][son]=a[son];//选
dp[0][son]=0;//不选
for(int i=head[son];i;i=e[i].next){
if(e[i].to!=fa){
dfs(e[i].to,son);
dp[1][son]=max(dp[1][son],dp[1][son]+dp[1][e[i].to]);
dp[0][son]=max(dp[0][son],dp[1][e[i].to]);
}
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n-1;i++){
scanf("%d %d",&u,&v);
add(u,v),add(v,u);
}
dfs(1,1);
ll ans=-0x3f3f3f3f3f3f3f3f;
for(int i=1;i<=n;i++){
ans=max(ans,dp[0][i]);
ans=max(ans,dp[1][i]);
}
printf("%lld\n",ans);
return 0;
}
蓝桥杯2015决赛四阶幻方题目链接
题目思路
我本来以为是全排列函数,后面发现跑不出15!的阶乘根本跑不出,后面发现是减无数次枝,就算枝减的少一点也没事,等他跑出来直接打表就行
代码
#include<cstdio>
using namespace std;
int a[20],b[20],ans;
void dfs(int step){
if(step==5){
if(a[1]+a[2]+a[3]+a[4]!=34){//第一行
return ;
}
}else if(step==9){
if(a[5]+a[6]+a[7]+a[8]!=34){//第二行
return ;
}
}else if(step==11){//主对角线
int sum=a[4]+a[7]+a[10];
if((34-sum>=2&&b[34-sum]!=0)||(34-sum<2)){
return ;
}
}else if(step==12){
int sum=a[1]+a[6]+a[11];
if((34-sum>=2&&b[34-sum]!=0)||(34-sum<2)){
return ;
}
}else if(step==13){//第三行
if(a[9]+a[10]+a[11]+a[12]!=34){
return ;
}
}else if(step==14){//第一列
if(a[1]+a[5]+a[9]+a[13]!=34){
return ;
}
if(a[4]+a[7]+a[10]+a[13]!=34){//次对角线
return ;
}
}else if(step==15){//第二列
if(a[2]+a[6]+a[10]+a[14]!=34){
return ;
}
}else if(step==16){//第三列
if(a[3]+a[7]+a[11]+a[15]!=34){
return ;
}
}else if(step==17){
if(a[13]+a[14]+a[15]+a[16]!=34){//第四行
return ;
}
if(a[4]+a[8]+a[12]+a[16]!=34){//第四列
return ;
}
if(a[1]+a[6]+a[11]+a[16]!=34){//主对角线
return ;
}
ans++;
return ;
}
for(int i=2;i<=16;i++){
if(!b[i]){
a[step]=i;
b[i]=1;
dfs(step+1);
b[i]=0;
}
}
}
int main(){
a[1]=1,b[1]=1;//初始化
dfs(2);
printf("%d\n",ans);
return 0;
}