10.11
T1 理想的正方形
题面
分析
容易想到
可以
查询时查询每个点往下
因为
点击查看代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 1000010
#define N 1010
#define int long long
using namespace std;
int a,b,n,G[N][N];
int max_x[N][N],min_x[N][N];
int Ans=2147483647,Ans_mx,Ans_mn;
template<typename T>void read(T &x)
{
x=0;char c=getchar();T neg=0;
while(!isdigit(c))neg|=!(c^'-'),c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg)x=(~x)+1;
}
template<typename T>void wr(T x)
{
if(x<0)putchar('-'),x=-x;
if(x>9)wr(x/10);
putchar((x-x/10*10)^48);
return ;
}
signed main()
{
// freopen("square.in","r",stdin);
// freopen("square.out","w",stdout);
read(a);read(b);read(n);
memset(min_x,127,sizeof min_x);
for(int i=1;i<=a;i++)
for(int j=1;j<=b;j++) read(G[i][j]);
for(int i=1;i<=a;i++)
{
for(int j=1;j<=b-n+1;j++)
{
for(int k=0;k<n;k++) max_x[i][j]=max(max_x[i][j],G[i][j+k]),min_x[i][j]=min(min_x[i][j],G[i][j+k]);
}
}
for(int i=1;i<=a-n+1;i++)
{
// cout<<endl;
for(int j=1;j<=b-n+1;j++)
{
Ans_mn=2147483647;
Ans_mx=0;
// cout<<i<<" "<<j<<" "<<max_x[i][j]<<" "<<min_x[i][j]<<endl;
// cout<<endl;
for(int k=0;k<n;k++)
{
Ans_mx=max(Ans_mx,max_x[i+k][j]);
Ans_mn=min(Ans_mn,min_x[i+k][j]);
// cout<<Ans_mx<<"-*-"<<Ans_mn<<" "<<Ans<<endl;
}
Ans=min(Ans,Ans_mx-Ans_mn);
}
}
wr(Ans);
return 0;
}
/*
5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
*/
T2 凸多边形的分割
分析
区间
考场上没想出来,想到是图论,每个点建边,
正解是 区间
常规变化将环拓展为
枚举
要合并到
例如枚举
如图
画个图应该很好理解
因此方程转移即为
注意区间小于
点击查看代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 1000010
#define N 200100
using namespace std;
int n;
__int128 dp[200][200],val[200];
__int128 Ans=(__int128)(1e30);
template<typename T>void read(T &x)
{
x=0;char c=getchar();T neg=0;
while(!isdigit(c))neg|=!(c^'-'),c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg)x=(~x)+1;
}
template<typename T>void wr(T x)
{
if(x<0)putchar('-'),x=-x;
if(x>9)wr(x/10);
putchar((x-x/10*10)^48);
return ;
}
inline __int128 Min(__int128 a, __int128 b) { return a < b ? a : b; }
signed main()
{
// freopen("abc10.in","r",stdin);
read(n);
for(int i=1;i<=n;i++) read(val[i]),val[i+n]=val[i];
for(int i=1;i<=2*n;i++)
{
for(int j=1;j<=2*n;j++) dp[i][j]=(__int128)(1e30);
}
for(int i=1;i<=2*n;i++) dp[i][i+1]=0;
for(int len=2;len<=n-1;len++)
{
for(int st=1;st<=n;st++)
{
for(int k=st+1;k<st+len;k++)
{
dp[st][st+len]=Min(dp[st][st+len],dp[st][k]+dp[k][st+len]+val[st]*val[st+len]*val[k]);
}
}
}
for(int i=1;i<=n;i++) Ans=Min(Ans,dp[i][i+n-1]);
wr(Ans);
return 0;
}
T3 电路维修
分析
最短路
容易想到,沿着可以走的路拓展
跑最短路即可
但本题有一个奇妙的性质
因为一直方向在右下
指向↘的电路都在
指向↗的电路都在
有了这个奇妙的性质就很好枚举可以到达的点了
↘可能到达的点
↗可能到达的点
然后用堆维护最短路
点击查看代码
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#include<cstring>
#define maxn 1000010
#define N 1010
#define int long long
using namespace std;
struct node{
int x,y,s;
bool operator<(const node x)const{ return s>x.s; }
}mi;
priority_queue< node > v;
int m,n,tx,ty,c;
char t;
bool G[618][618];
bool f[618][618];
int dx[2][6]={0,0,1,-1,1,-1, 0,0,1,-1,1,-1};
int dy[2][6]={1,-1,0,0,1,-1, 1,-1,0,0,-1,1};
signed main()
{
// freopen("cir.in","r",stdin);
// freopen("cir.out","w",stdout);
scanf("%lld",&c);
while(c--)
{
scanf("%lld%lld",&m,&n);
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
{
cin>>t;
if(t=='/')
G[i][j]=1;
else
G[i][j]=0;
}
if((m+n)%2)
{
cout<<"NO SOLUTION"<<endl;
continue;
}
mi.x=1;
mi.y=1;
mi.s=G[1][1];
v.push(mi);
while(v.size())
{
node st=v.top();
if(st.x==m&&st.y==n)
{
printf("%lld\n",st.s);
break;
}
for(int i=0;i<6;i++)
{
tx=st.x+dx[(st.x+st.y)%2][i];
ty=st.y+dy[(st.x+st.y)%2][i];
if(tx>0&&ty>0&&tx<=m&&ty<=n&&!f[tx][ty])
{
f[tx][ty]=1;
mi.x=tx; mi.y=ty;
if((tx+ty)%2==G[tx][ty]) mi.s=st.s;
else mi.s=st.s+1;
v.push(mi);
}
}
v.pop();
}
while(v.size())
v.pop();
memset(f,0,sizeof(f));
}
return 0;
}
/*
1
3 5
\\/\\
\\///
/\\\\
*/
T4 换教室
没有什么比小花讲的更好了
点击查看代码
#include<bits/stdc++.h>
#define maxn 2010
#define int long long
using namespace std;
int n,m,v,e;
int c[maxn],d[maxn];
double p[maxn];
double dp[maxn][maxn][2],f[maxn][maxn];
int u,r;
double val;
inline double min(double a,double b){
return a<b?a:b;
}
inline int read(){
int k = 0;
char c;
c = getchar();
while(!isdigit(c))c = getchar();
while(isdigit(c)){
k = (k<<1)+(k<<3)+c-48;
c = getchar();
}
return k ;
}
signed main()
{
// freopen("classroom4.in","r",stdin);
scanf("%lld%lld%lld%lld",&n,&m,&v,&e);// num limit tot edge// 注意#define int long long
for(int i=1;i<=n;i++) c[i]=read();
for(int i=1;i<=n;i++) d[i]=read();
for(int i=1;i<=n;i++) cin>>p[i];
memset(f,0x7f,sizeof f);// double 可以使用 memset
for(int i=1;i<=e;i++)
{
u=read(); r=read();val=read();
f[u][r]=f[r][u]=min(f[u][r],val);
}
for(int k=1;k<=v;k++)// Floyd 的 k 放在外层
for(int i=1;i<=v;i++)
for(int j=i+1;j<=v;j++)
f[i][j]=f[j][i]=min(f[i][j],f[i][k]+f[k][j]);
for(int i=1;i<=v;i++) f[i][i]=0;// 注意 自己到自己 距离为 0 (感谢tyj
memset(dp,0x7f,sizeof dp);// double 可以使用 memset
dp[1][0][0]=dp[1][1][1]=0;
for(int i=2;i<=n;i++){// 大好的 DP
double add1=f[c[i-1]][c[i]];
for(int j=0;j<=min(m,i);j++)
{
dp[i][j][0]=min(dp[i-1][j][0]+add1,dp[i-1][j][1]+f[d[i-1]][c[i]]*p[i-1]+f[c[i-1]][c[i]]*(1-p[i-1]));
if(j!=0)
dp[i][j][1]=min(dp[i-1][j-1][0]+f[c[i-1]][d[i]]*p[i]+f[c[i-1]][c[i]]*(1-p[i]),dp[i-1][j-1][1]+f[c[i-1]][c[i]]*(1-p[i-1])*(1-p[i])+f[c[i-1]][d[i]]*(1-p[i-1])*p[i]+f[d[i-1]][c[i]]*(1-p[i])*p[i-1]+f[d[i-1]][d[i]]*p[i-1]*p[i]);
}
}
double hahaha=9999999999;
for(int i=0;i<=m;i++)
{
hahaha=min(dp[n][i][0],min(dp[n][i][1],hahaha));
}
printf("%.2lf",hahaha);
}
/*
3 2 3 3
2 1 2
1 2 1
0.8 0.2 0.5
1 2 5
1 3 3
2 3 1
*/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!