2022.9.20测试
一测330,原因T4是乱打else导致炸了。
T1:P2327 [SCOI2005]扫雷(黄)
T2:P1896 [SCOI2005] 互不侵犯(蓝)
T3:P2330 [SCOI2005]繁忙的都市(黄)
T4:2331 [SCOI2005]最大子矩阵(蓝)
T1:
记录
那么要满足:
那么就可以转移了
最后统计
#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
const int N=1e4+5;
int n,a[N],dp[N][2][2];
signed main()
{
freopen("sweeper.in","r",stdin);
freopen("sweeper.out","w",stdout);
scanf("%lld",&n);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
if(a[1]||a[2])dp[1][1][0]=1;
dp[1][0][0]=1;
for(int i=2;i<=n;i++)
{
for(int j=0;j<2;j++)
{
for(int k=0;k<2;k++)
{
if(j+k>a[i])break;
for(int l=0;l<2;l++)
{
if(j+k+l!=a[i-1])continue;
dp[i][j][k]+=dp[i-1][k][l];
}
}
}
}
int ans=0;
for(int i=0;i<2;i++)for(int j=0;j<2;j++)if(i+j==a[n])ans+=dp[n][i][j];
printf("%lld",ans);
return 0;
}
T2:
经典状压模板,不讲了。
设
首先同行国王不能互相攻击,所以
另外不同行的国王也不能互相攻击,设上一行的状态为
先预处理出来合法的
最后进行dp转移。
然后答案为
#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
const int N=9;
int n,k,dp[N+1][N*N+1][1<<N],p[1<<N],vis[1<<N];
inline int lowbit(int x)
{
return x&(-x);
}
void pre()
{
for(int i=0;i<1<<n;i++)
{
if((i&(i<<1))||(i&(i>>1)))continue;
vis[i]=1;
int x=i;
while(x)x-=lowbit(x),p[i]++;
}
}
signed main()
{
freopen("king.in","r",stdin);
freopen("king.out","w",stdout);
scanf("%lld%lld",&n,&k);
pre();
for(int i=0;i<1<<n;i++)if(vis[i])dp[1][p[i]][i]=1;
for(int i=2;i<=n;i++)
{
for(int j=0;j<1<<n;j++)
{
if(!vis[j])continue;
for(int t=0;t<1<<n;t++)
{
if(!vis[t])continue;
if((j&t)||(j&(t<<1))||(j&(t>>1)))continue;
for(int q=p[j]+p[t];q<=k;q++)dp[i][q][j]+=dp[i-1][q-p[j]][t];
}
}
}
int ans=0;
for(int i=0;i<1<<n;i++)ans+=dp[n][k][i];
printf("%lld",ans);
return 0;
}
T3:
题看完以后就是个最小生成树,然后就没了。
要求要所有点连通,且边最少,所以取
然后要求取出的所有边的权值最大值最小,那么每次贪心取最小边,如果这个边连接的两个点已在一个子图,那么不能选取这条边。可以利用并查集判断两个点是否在一个子图。
实质上就是做最小生成树的工作。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5+5;
int n,m,f[N];
struct node
{
int from,to,data;
}a[N];
bool cmp(node fi,node se)
{
return fi.data<se.data;
}
int afind(int x)
{
if(x==f[x])return x;
return f[x]=afind(f[x]);
}
int krus()
{
sort(a+1,a+1+m,cmp);
int ans=0;
for(int i=1;i<=m;i++)
{
if(afind(a[i].from)==afind(a[i].to))continue;
f[afind(a[i].from)]=afind(a[i].to);
ans=a[i].data;
}
return ans;
}
int main()
{
freopen("city.in","r",stdin);
freopen("city.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)f[i]=i;
for(int i=1;i<=m;i++)scanf("%d%d%d",&a[i].from,&a[i].to,&a[i].data);
int ans=krus();
printf("%d %d",n-1,ans);
return 0;
}
T4:
根据数据范围
1.当
k个最大字段和问题。
记录
当
当
2.当
这个时候对于每一层的数,状态变多了起来,这里选择穷举所有状态。
设状态为
当
当
当
当
当
那又可以列dp方程了,设
当此层状态
当
当
当
当
当
若此层状态与上层状态不同,那么矩阵数目会随之改变。
当
当
特殊情况:当
当
特殊情况:当
当
当
当特殊情况
注意:上述所有的特殊情况并不代表只从特殊情况转移,而是要与一般情况做比较取最优解。
然后求出
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=105;
const int K=15;
int n,m,k,a[2][N],dp[N][5][K],f[N][K][2];
int main()
{
freopen("matrix.in","r",stdin);
freopen("matrix.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)for(int j=0;j<m;j++)scanf("%d",&a[j][i]);
if(m==1)
{
memset(f,-0x3f,sizeof(f));
f[0][0][0]=0;
for(int i=1;i<=n;i++)
{
for(int j=0;j<=k;j++)
{
f[i][j][0]=max(f[i-1][j][0],f[i-1][j][1]);
if(j>0)f[i][j][1]=max(f[i-1][j-1][0]+a[0][i],max(f[i-1][j-1][1]+a[0][i],f[i-1][j][1]+a[0][i]));
}
}
int ans=max(f[n][k][0],f[n][k][1]);
printf("%d",ans);
return 0;
}
memset(dp,-0x3f,sizeof(dp));
dp[0][0][0]=0;
for(int i=1;i<=n;i++)
{
for(int j=0;j<5;j++)
{
for(int t=0;t<5;t++)
{
for(int p=0;p<=k;p++)
{
if(j!=t&&p>0)
{
if(j==1)dp[i][j][p]=max(dp[i][j][p],a[0][i]+dp[i-1][t][p-1]);
if(j==1&&t==4)dp[i][j][p]=max(dp[i][j][p],a[0][i]+dp[i-1][t][p]);
if(j==2)dp[i][j][p]=max(dp[i][j][p],a[1][i]+dp[i-1][t][p-1]);
if(j==2&&t==4)dp[i][j][p]=max(dp[i][j][p],a[1][i]+dp[i-1][t][p]);
if(j==3)dp[i][j][p]=max(dp[i][j][p],a[0][i]+a[1][i]+dp[i-1][t][p-1]);
if(j==0)dp[i][j][p]=max(dp[i][j][p],dp[i-1][t][p]);
if(j==4)
{
if(p>=2)dp[i][j][p]=max(dp[i][j][p],dp[i-1][t][p-2]+a[0][i]+a[1][i]);
if(t==2||t==1)dp[i][j][p]=max(dp[i][j][p],dp[i-1][t][p-1]+a[0][i]+a[1][i]);
}
}
if(j==t)
{
if(j==0)dp[i][j][p]=max(dp[i][j][p],dp[i-1][t][p]);
if(j==1)dp[i][j][p]=max(dp[i][j][p],a[0][i]+dp[i-1][t][p]);
if(j==2)dp[i][j][p]=max(dp[i][j][p],a[1][i]+dp[i-1][t][p]);
if(j==3)dp[i][j][p]=max(dp[i][j][p],a[0][i]+a[1][i]+dp[i-1][t][p]);
if(j==4)dp[i][j][p]=max(dp[i][j][p],a[0][i]+a[1][i]+dp[i-1][t][p]);
}
}
}
}
}
int ans=-1e9;
for(int i=0;i<5;i++)ans=max(ans,dp[n][i][k]);
printf("%d",ans);
return 0;
}
/*
3 2 1
-1 2
2 -3
3 1
*/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】