思考起来很简单,对于任意一个输入的,它会约束的格子只有三个,也就是只要算出当前在位置摆放的情况,就能算出位置的情况,显然(place数组是摆放情况)是不确定的,所以我们需要计算它为1或0的两种可能性,递推式也不难想到:
如果当前的算出来不等于当前的情况就可以作废
最后如果(即不用在摆放就可以满足),那么
点击查看代码
| #include<bits/stdc++.h> |
| using namespace std; |
| const int maxn=1e6; |
| int a[maxn];int pl[maxn]; |
| bool valid(int x){return x==1||x==0;} |
| int ans=0;int n; |
| void calc(int f) |
| { |
| memset(pl,0,sizeof pl); |
| pl[1]=f;int flag=0; |
| for(int i=2;i<=n+1;i++) |
| { |
| pl[i]=a[i-1]-pl[i-1]-pl[i-2]; |
| if(!valid(pl[i])) |
| { |
| flag=1; |
| break; |
| } |
| } |
| if(pl[n+1]==0&&flag==0)ans++; |
| } |
| |
| |
| int main() |
| { |
| freopen("sweeper.in","r",stdin); |
| freopen("sweeper.out","w",stdout); |
| scanf("%d",&n); |
| for(int i=1;i<=n;i++)scanf("%d",&a[i]); |
| calc(0),calc(1); |
| printf("%d",ans); |
| return 0; |
| } |
义眼状压,定义为前行一共填了个数,当前第行填的是第个合法数时的方案数
遍历 ,如果i&(i<<1))||i&(i>>1)那么当前是不合法的,跳过
否则放入数组里并记录其二进制下1的个数
其中:
为定义所示,枚举的是行填的数,是当前这个数的1的个数
(是总共有效数字个数)
点击查看代码
| #include<bits/stdc++.h> |
| #define int long long |
| using namespace std; |
| const int maxn=10; |
| long long dp[maxn][1<<maxn-1][100]; |
| int n,k; |
| int sta[1<<maxn+10],cnt; |
| int num[1<<maxn+10]; |
| int count_one(int x) |
| { |
| int ans=0; |
| while(x) |
| { |
| if(x&1)ans++; |
| x>>=1; |
| } |
| return ans; |
| } |
| void pre() |
| { |
| for(int i=0;i<=(1<<n)-1;i++) |
| { |
| if((i&(i<<1))||(i&(i>>1)))continue; |
| sta[++cnt]=i,num[cnt]=count_one(i); |
| } |
| } |
| signed main() |
| { |
| freopen("king.in","r",stdin); |
| freopen("king.out","w",stdout); |
| scanf("%d%d",&n,&k); |
| pre(); |
| for(int j=1;j<=cnt;j++)dp[1][j][num[j]]=1; |
| for(int i=2;i<=n;i++) |
| for(int j=1;j<=cnt;j++) |
| for(int las=1;las<=cnt;las++) |
| { |
| if((sta[j]&sta[las])||(sta[j]&(sta[las]<<1))||(sta[j]&(sta[las]>>1)))continue; |
| for(int plc=num[j];plc<=k;plc++) |
| dp[i][j][plc]+=dp[i-1][las][plc-num[j]]; |
| } |
| long long ans=0; |
| for(int i=1;i<=cnt;i++)ans+=dp[n][i][k]; |
| printf("%lld",ans); |
| return 0; |
| } |
| |
义眼弱智最小生成树板子
点击查看代码
| #include<bits/stdc++.h> |
| using namespace std; |
| const int maxn=1e6+10000; |
| struct Edge{int u,v,nex;int w;}E[maxn]; |
| int tote,head[maxn]; |
| void add(int u,int v,int w) |
| { |
| E[++tote].u=u,E[++tote].v=v,E[tote].w=w; |
| E[tote].nex=head[u],head[u]=tote; |
| } |
| inline int read() |
| { |
| int x=0,f=1; |
| char c=getchar(); |
| while(c<'0'||c>'9') |
| { |
| if(c=='-')f=-1; |
| c=getchar(); |
| } |
| while('0'<=c&&c<='9') |
| { |
| x=(x<<1)+(x<<3)+(c^48); |
| c=getchar(); |
| } |
| return x*f; |
| } |
| int f[maxn];int ans=-1; |
| int find(int x){return x==f[x]?x:f[x]=find(f[x]);} |
| bool cmp(Edge x,Edge y){return x.w<=y.w;} |
| int main() |
| { |
| |
| |
| int n,m; |
| n=read(),m=read(); |
| int u,v,w; |
| for(int i=1;i<=n;i++)f[i]=i; |
| for(int i=1;i<=m;i++) |
| E[i].u=read(),E[i].v=read(),E[i].w=read(); |
| sort(E+1,E+m+1,cmp); |
| int sel=0; |
| for(int i=1;i<=m-1;i++) |
| { |
| int fu=find(E[i].u),fv=find(E[i].v); |
| if(fu==fv)continue; |
| else |
| { |
| f[fu]=fv; |
| sel++; |
| ans=max(ans,E[i].w); |
| } |
| } |
| printf("%d %d",sel,ans); |
| return 0; |
| } |
| |
| |
| |
| |
| |
| |
| |
这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大。注意:选出的k个子矩阵不能相互重叠。
第一行为n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下来n行描述矩阵每行中的每个元素的分值(每个元素的分值的绝对值不超过32767)。
只有一行为k个子矩阵分值之和最大为多少。
首先定义(在不同的情况下表示不同的含义)
分别表示当前列选与不选
(其中有关于的都是枚举直接新建块,不做拼接操作)
那么代码就好写了,唯一的坑点是,枚举情况的时候,默认已经大于等于了,所以要特判
点击查看代码
| #include<bits/stdc++.h> |
| #define int long long |
| using namespace std; |
| const int maxn=10000; |
| const int maxk=15; |
| int sum[3][maxn]; |
| int mat[maxn][3]; |
| int n,m,k; |
| int dp[maxn][maxk][7]; |
| signed main() |
| { |
| scanf("%lld%lld%lld",&n,&m,&k); |
| for(int i=1;i<=n;i++) |
| for(int j=1;j<=m;j++)scanf("%lld",&mat[i][j]); |
| if(m==1) |
| { |
| for(int i=1;i<=n;i++) |
| { |
| for(int j=0;j<=k;j++) |
| { |
| dp[i][j][0]=max(dp[i-1][j][1],dp[i-1][j][0]); |
| if(j>=1) |
| dp[i][j][1]=max(dp[i-1][j][1],max(dp[i-1][j-1][1],dp[i-1][j-1][0]))+mat[i][1]; |
| } |
| } |
| printf("%lld",max(dp[n][k][1],dp[n][k][0])); |
| } |
| else |
| { |
| for(int i=1;i<=n;i++) |
| { |
| for(int j=0;j<=k;j++) |
| { |
| int maxx=-1;for(int t=1;t<=5;t++)maxx=max(maxx,dp[i-1][j-1][t]); |
| for(int t=1;t<=5;t++)dp[i][j][1]=max(dp[i][j][1],dp[i-1][j][t]); |
| if(j!=0) |
| { |
| dp[i][j][2]=max(max(dp[i-1][j][2],dp[i-1][j][5]),maxx)+mat[i][1]; |
| dp[i][j][3]=max(max(dp[i-1][j][3],dp[i-1][j][5]),maxx)+mat[i][2]; |
| dp[i][j][4]=max(dp[i][j][4],dp[i-1][j][4]+mat[i][1]+mat[i][2]); |
| dp[i][j][4]=max(dp[i][j][4],maxx+mat[i][1]+mat[i][2]); |
| } |
| if(j>=2) |
| { |
| dp[i][j][5]=max(dp[i][j][5],max(max(dp[i-1][j-1][2],dp[i-1][j-1][3]),dp[i-1][j][5])+mat[i][1]+mat[i][2]); |
| maxx=-1;for(int t=1;t<=5;t++)maxx=max(maxx,dp[i-1][j-2][t]); |
| dp[i][j][5]=max(dp[i][j][5],maxx+mat[i][1]+mat[i][2]); |
| } |
| } |
| } |
| long long ans=-1ll; |
| for(int i=1;i<=5;i++)ans=max(ans,dp[n][k][i]); |
| printf("%lld",ans); |
| } |
| return 0; |
| } |


【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!