洛谷刷题7.7
P2622 关灯问题 II - 洛谷
本质是bfs求最短路,通常我们的状态是一个点,现在我们的状态是01数组,我们可以将它转换成十进制来简便的表示状态,但是状态转移时要熟悉位运算。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int arr[101][11];
int n,m,step[1025];
queue<int>q;
bool wei(int x,int y){x >>= y;return x&1;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)for(int j=0;j<n;j++)cin>>arr[i][j];
q.push((1<<n)-1);//全开
step[(1<<n)-1] = 1;
while(!q.empty()){int now = q.front();q.pop(); if(now == 0){cout<<step[0]-1;return 0;}for(int i=1;i<=m;i++){int temp =now;for(int j=0;j<n;j++){if(arr[i][j] == 1 && wei(temp,j)) temp ^= (1<<j);else if(arr[i][j] == -1 && !wei(temp,j)) temp |= (1<<j);}if(step[temp] == 0){step[temp] = step[now] + 1;q.push(temp);}}
}
cout<<-1;return 0;
}
P1336 最佳课题选择 - 洛谷
简单的部分背包
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll dp[205],n,m,a,b;
int main()
{
cin>>n>>m;
memset(dp,0x3f,sizeof(dp));
dp[0]=0;
while(m--){cin>>a>>b;for(int i=n;i>=1;i--){for(int j=0;j<=i;j++){dp[i]=min(dp[i],dp[i-j]+a*(ll)pow(j,b));}}
}
cout<<dp[n];return 0;
}
P1474 [USACO2.3] Money System / [USACO07OCT]Cow Cash G - 洛谷
简单的完全背包求方案数
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,v,dp[10005],a;
int main()
{
cin>>v>>n;
dp[0]=1;
while(v--){cin>>a;for(int i=a;i<=n;i++) dp[i]+=dp[i-a];
}
cout<<dp[n];return 0;
}
P1077 [NOIP 2012 普及组] 摆花 - 洛谷
简单的01背包求方案数
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,m,dp[10005],a,mod=1000007;
int main()
{
cin>>n>>m;
dp[0]=1;
while(n--){cin>>a;for(int i=m;i>=0;i--){for(int j=1;j<=min(i,(int)a);j++){dp[i]+=dp[i-j];dp[i]%=mod;}}
}
cout<<dp[m];return 0;
}
P1141 01迷宫 - 洛谷
这题有个优化小技巧,记录哪个点是在哪个时间访问的,再通过这个时间去映射到块的大小。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,m,ans[1005][1005],v[100005],sum,a,b,now=1;
char arr[1005][1005];
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
void bfs(int sx,int sy,int num){sum=1;queue<pair<int,int> >r;r.push(make_pair(sx,sy));ans[sx][sy]=num;while(!r.empty()){int x = r.front().first,y = r.front().second;r.pop();for(int i=0;i<4;i++){if(x+dx[i]>=1&&x+dx[i]<=n&&y+dy[i]>=1&&y+dy[i]<=n){if(arr[x][y]!=arr[x+dx[i]][y+dy[i]]&&ans[x+dx[i]][y+dy[i]]==0){ans[x+dx[i]][y+dy[i]]=num;sum++;r.push(make_pair(x+dx[i],y+dy[i]));}}}}v[num]=sum;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)cin>>arr[i][j];
while(m--){cin>>a>>b;if(ans[a][b]) cout<<v[ans[a][b]]<<endl;else{bfs(a,b,now++);cout<<v[ans[a][b]]<<endl;}
}return 0;
}
P8673 [蓝桥杯 2018 国 C] 迷宫与陷阱 - 洛谷
广搜,注意记录该点是否访问是要记录该点的坐标和剩余无敌的步数。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct point{int x,y,t,step;//无敌时间
};
int n,k,dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
char arr[1005][1005];
bool vis[1005][1005][11];//第三维是时间
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)cin>>arr[i][j];
queue<point>r;
r.push(point{1,1,0,0});
while(!r.empty()){int x=r.front().x,y=r.front().y,t=r.front().t,s=r.front().step;if(x==n&&y==n){cout<<s;return 0;}r.pop();for(int i=0;i<4;i++){if(x+dx[i]>=1&&x+dx[i]<=n&&y+dy[i]>=1&&y+dy[i]<=n){if(arr[x+dx[i]][y+dy[i]]=='.'||(arr[x+dx[i]][y+dy[i]]=='X'&&t>0)){if(!vis[x+dx[i]][y+dy[i]][max(t-1,0)]){r.push(point{x+dx[i],y+dy[i],max(t-1,0),s+1});vis[x+dx[i]][y+dy[i]][max(t-1,0)]=true;} }if(arr[x+dx[i]][y+dy[i]]=='%'){arr[x+dx[i]][y+dy[i]]='.';r.push(point{x+dx[i],y+dy[i],k,s+1});vis[x+dx[i]][y+dy[i]][k]=true;}}}
}
cout<<-1;return 0;
}
P12323 [蓝桥杯 2023 省 Java B] 阶乘求和 - 洛谷
注意该题只取后9位,当i>=40时,40!,41!后9位都是0,所以只用循环到39.
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll ans=0,now=1,mod=1000000000;
int main()
{
for(ll i =1;i<=40;i++){
// now *= (i%mod);now *= i;now %= mod;ans += now;ans %= mod;
}
cout<<ans;return 0;
}