过题情况
第一题:100%
第二题:100%
第三题:100%
第四题:100%
第五题:100%
第一题
经典区间dp问题,dp[i][j]代表着从字符串i位置到j位置需要的最小括号匹配数,如果第i个位置和第j个位置的两个括号是匹配的,那么dp[i][j] = dp[i+1][j-1],相当于两边分别往里缩了一个;当i<j时,dp[i][j] = dp[i][k]+dp[k+1][j] ;
#include<bits/stdc++.h>
using namespace std;
const int maxn=222;
int dp[maxn][maxn];
int main(){
string s;cin>>s;
int len=s.length();
for(int i=0;i<len;i++)
dp[i][i]=1;
for(int l = 1; l < len; l++){
for(int i = 0; i < len - l; i++){
int j = i + l;
dp[i][j]=len;
if((s[i]=='[' && s[j]==']') || (s[i]=='(' && s[j]==')'))
dp[i][j] = min(dp[i][j], dp[i+1][j-1]);
for(int k = i; k < j; k++)
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j]);
}
}
printf("%d\n",dp[0][len-1]);
}
第二题:
学过高数的都会,简单的一个积分题
#include<bits/stdc++.h>
using namespace std;
double solve(double a, double b, double x){
return a*x*x*x/3+x*x/2+b*x;
}
int main(){
int T;scanf("%d",&T);
while(T--){
double A,B,C,D;
cin>>A>>B>>C>>D;
double ans=solve(A,B,D)-solve(A,B,C);
printf("%lf\n",ans);
}
}
第三题:
很简单答案为C(n,1)*1+C(n,2)*2+C(n,3)*3…,看到这是不是很熟悉了
ans=C(n,0)*0+C(n,1)*1+C(n,2)*2+C(n,3)3…+C(n,n)n 正着写
ans=C(n,n)n+C(n,n-1)(n-1)+… 反着写
两个加起来2ans=n2^n
ans=n2^(n-1)即可,用快速幂
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
long long quick_pow(long long a,long long b){
long long ans=1;
while(b){
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
int main(){
long long n;
cin>>n;
cout<<n*quick_pow(2, n-1)%mod<<endl;
}
第四题:
STL大法好,set+map轻松做到排序+计数
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+200;
set<int>g[maxn];
int main(){
int n,m;
scanf("%d%d",&n,&m);
while(m--){
int x,y;
scanf("%d%d",&x,&y);
g[x].insert(y);
g[y].insert(x);
}
map<set<int>, int>q;
for(int i=1;i<=n;i++)
if(g[i].size()!=0)
q[g[i]]+=1;
long long ans=0;
map<set<int>, int>::iterator it;
for(it=q.begin();it!=q.end();it++){
int num=it->second;
if(num>1)
ans+=1ll*num*(num-1)/2;
}
cout<<ans<<endl;
}
第五题
很简单的想法,最短路即可,注意!!!坑点在于有重边,我还暴力写了个dfs+剪枝,过了55%
最短路
#include<bits/stdc++.h>
using namespace std;
const int INF=1e9;
const int maxn=2222;
int v[maxn];
int dis[maxn], a[maxn][maxn];
int n,m,k;
void Dj()
{
for (int i = 2; i <= n; i++)
dis[i] = INF;
dis[1] = 0;
memset(v, 0, sizeof(v));
for (int i = 1; i <= n; i++)
{
int u = -1, minn = INF;
for (int j = 1; j <= n;j++)
if (v[j] == 0 && dis[j] < minn)
{
minn = dis[j]; u = j;
}
if(u==-1)
break;
v[u] = 1;
for (int j = 1; j <= n; j++)
if (v[j] == 0)dis[j] = min(dis[j], dis[u] + a[u][j]);
}
}
int main(){
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
a[i][j]=INF;
while(m--){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
a[x][y]=min(a[x][y],z);
a[y][x]=min(a[y][x],z);
}
while(k--){
int x,y;
scanf("%d%d",&x,&y);
a[x][y]=0;
}
Dj();
if(dis[n]==INF)
dis[n]=-1;
cout<<dis[n]<<endl;
}
暴力dfs
#include<bits/stdc++.h>
using namespace std;
const int maxn=2222;
vector<pair<int,int> >G[maxn];
vector<int>K[maxn];
int n,m,k,ans=1e9;
int vis[maxn];
void dfs(int u,int fa,int step){
if(u==n){
if(step<ans)
ans=step;
return;
}
if(step>=ans)
return;
for(int i=0;i<K[u].size();i++){
int v=K[u][i];
if(v==fa||vis[v])
continue;
vis[v]=1;
dfs(v,u,step);
vis[v]=0;
}
for(int i=0;i<G[u].size();i++){
int v=G[u][i].first, w=G[u][i].second;
if(v==fa||vis[v])
continue;
vis[v]=1;
dfs(v,u,step+w);
vis[v]=0;
}
}
int main(){
cin>>n>>m>>k;
while(m--){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
G[x].push_back(make_pair(y,z));
G[y].push_back(make_pair(x,z));
}
while(k--){
int x,y;
scanf("%d%d",&x,&y);
K[x].push_back(y);
}
vis[1]=1;
dfs(1,0,0);
if(ans==1e9)
ans=-1;
cout<<ans<<endl;
}