D. 题目要找如题目所示的那种菱形的个数
只要DFS两层,看每个点走两步都可以到哪些点,记录下来,最后就是组合数统计一下和就行了。
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
vector<int> edge[3005];
int ans[3005][3005];
void dfs(int t,int s,int step)
{
int i;
if (step==2)
{
ans[s][t]++;
return;
}
for (i=0;i<edge[t].size();i++)
{
dfs(edge[t][i],s,step+1);
}
}
int main()
{
int i,j,n,m,x,y;
scanf("%d%d",&n,&m);
for (i=0;i<m;i++)
{
scanf("%d%d",&x,&y);
edge[x].push_back(y);
}
for (i=1;i<=n;i++)
{
dfs(i,i,0);
}
long long s=0;
for (i=1;i<=n;i++)
{
for (j=1;j<=n;j++)
{
if (i==j) continue;
s+=(ans[i][j]*(ans[i][j]-1))/2;
}
}
printf("%I64d\n",s);
return 0;
}
E. 最优比例的问题
题目要求的是(d1+d2+d3+....)/(b1+b2+b3+....)的比例最小,假设(d1+d2+...)/(b1+b2+b3+...)的最小值为r,则有(d1+d2+...)/(b1+b2+...)>=r
整理一下得到(d1-b1*r)+(d2-b2*r)+...>=0
所以可以二分r,然后O(n^2)计算左边部分的最小值,看是否大于0,如果大于0,则扩大r,否则缩小r。
代码
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define eps 1e-9
int x[1005];
int b[1005];
double dp[1005];
int before[1005];
int n,l;
bool checkValid(double r)
{
int i,j;
for (i=0;i<=n;i++) dp[i]=1e12;
dp[0]=0;
for (i=1;i<=n;i++)
{
for (j=0;j<i;j++)
{
double tmp=dp[j]+sqrt(abs(l-(x[i]-x[j]))*1.0)-r*b[i];
if (tmp<dp[i])
{
dp[i]=tmp;
before[i]=j;
}
}
}
return dp[n]>0;
}
void printAns(int t)
{
if (t==0) return;
printAns(before[t]);
printf("%d",t);
if (t<n) printf(" ");
}
int main()
{
int i,j;
scanf("%d%d",&n,&l);
x[0]=b[0]=0;
for (i=1;i<=n;i++)
{
scanf("%d%d",&x[i],&b[i]);
}
double l=0,r=1e7;
while((r-l)>eps)
{
double mid=(l+r)/2;
if (checkValid(mid)) l=mid;
else r=mid;
}
printAns(n);
return 0;
}F. 简单dp,dp[i][j]表示还剩下i列没有1,j列只有一个1的方法数,然后三种转移方式:找两列没有1的都加上1,找一列没有1,一列只有一个1的加上1,还有找两列只有一个1的,都加上1,最后dp[0][0]就是答案。
代码
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
char str[1000];
int init[1000];
long long dp[505][505];
int main()
{
int i,j,n,m,mod;
scanf("%d%d%d",&n,&m,&mod);
memset(init,0,sizeof(init));
for (i=0;i<m;i++)
{
scanf("%s",str);
for (j=0;j<n;j++)
{
if (str[j]=='1') init[j]++;
}
}
int zero=0,one=0;
for (i=0;i<n;i++)
{
if (init[i]==0) zero++;
else if (init[i]==1) one++;
}
memset(dp,0,sizeof(dp));
dp[zero][one]=1;
for (i=zero;i>=0;i--)
{
for (j=n;j>=0;j--)
{
if (i>=2) dp[i-2][j+2]+=(long long)i*(i-1)/2*dp[i][j]%mod;
if (i>=1 && j>=1) dp[i-1][j]+=(long long)i*j*dp[i][j]%mod;
if (j>=2) dp[i][j-2]+=(long long)j*(j-1)/2*dp[i][j]%mod;
}
}
printf("%I64d\n",dp[0][0]);
return 0;
}
本文提供了三道算法题目的详细解答思路与实现代码,包括菱形计数问题、最优比例问题及简单的动态规划问题。
515

被折叠的 条评论
为什么被折叠?



