Codeforces Round #533 (Div. 2) C.思维dp D. 多源BFS
题目链接:https://codeforces.com/contest/1105
C. Ayoub and Lost Array
题目大意:一个长度为n的数组,数组的元素都在[L,R]之间,并且数组全部元素的和可以被3整除,问有多少种方法构建出该数组。答案模1000000007
例
2 1 3
3
note:满足的情况只有[1,2],[2,1],[3,3]
解题思路:用dp[i][j]表示长度为i的数组,元素大小在[L,R]之间,并且元素和模3的余数为j的方案数,我们可以计算出[L,R]范围内模3余0\1\2的数的个数,分别设为num0,num1,num2, 我们可以很容易知道dp[1][0]=num0,dp[1][1]=num1,dp[1][2]=num2,而dp[2][0]需要分情况,当前1个数和模3余0时,第2个数便只能放模3余0的数,即有dp[1][0]*num0种;当前1个数和模3余1时,第2个数便只能放模3余2的数,即有dp[1][1]*num2种;当前1个数和模3余2时,第2个数便只能放模3余1的数,即有dp[1][2]*num1种。dp[n][0]即为我们要求的答案。
于是我们便可以得出递推式:
dp[i][0]=((dp[i-1][0]*num0%mod+dp[i-1][1]*num2%mod)%mod+dp[i-1][2]*num1%mod)%mod;
dp[i][1]=((dp[i-1][0]*num1%mod+dp[i-1][1]*num0%mod)%mod+dp[i-1][2]*num2%mod)%mod;
dp[i][2]=((dp[i-1][0]*num2%mod+dp[i-1][1]*num1%mod)%mod+dp[i-1][2]*num0%mod)%mod;
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<string> #include<set> #include<cmath> #include<list> #include<deque> #include<cstdlib> #include<bitset> #include<stack> #include<map> #include<queue> using namespace std; typedef long long ll; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define pushup() tree[rt]=tree[rt<<1]+tree[rt<<1|1] const int INF=0x3f3f3f3f; const double PI=acos(-1.0); const double eps=1e-6; const ll mod=1e9+7; const int maxn=100005; ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} ll lcm(ll a,ll b){return a/gcd(a,b)*b;} ll dp[2000005][5]; ll n,l,r; int main() { ios::sync_with_stdio(false); cin.tie(0); cin>>n>>l>>r; ll num0=r/3-(l-1)/3; ll num1=num0; ll num2=num0; int i,j; for(i=l;i<=r;i++) { if(i%3==0)break; else if(i%3==1)num1++; else num2++; } for(j=r;j>=i;j--) { if(j%3==2)break; else if(j%3==1) { num2--; break; } else if(j%3==0) { num1--; num2--; break; } } dp[1][0]=num0; dp[1][1]=num1; dp[1][2]=num2; for(int i=2;i<=n;i++) { dp[i][0]=((dp[i-1][0]*num0%mod+dp[i-1][1]*num2%mod)%mod+dp[i-1][2]*num1%mod)%mod; dp[i][1]=((dp[i-1][0]*num1%mod+dp[i-1][1]*num0%mod)%mod+dp[i-1][2]*num2%mod)%mod; dp[i][2]=((dp[i-1][0]*num2%mod+dp[i-1][1]*num1%mod)%mod+dp[i-1][2]*num0%mod)%mod; } cout<<dp[n][0]<<endl; return 0; }
D. Kilani and the Game
题目大意:给出一个n*m的地图,最多9个人,每个人至少含有一个城堡,同时有每个人的扩张速度,即可以连续扩张的次数,现在从1-n轮流从各自的城堡开始扩张,不可通过障碍,求整个地图被扩张完成后,各个人所占领城堡的数目。
Examples
input
3 3 2
1 1
1..
...
..2
output
6 3
解题思路:开始就是想bfs嵌套,先把每一个玩家从1-n的城堡压入第一个队列,再每次把第一个队列的第一个元素弹出,压入第二个队列继续进行bfs,,一直不知道哪里错了,看了别人博客后才发现那样是错的,如果那样做的话,对于这个样例是过不了的:
2 1
1..
1..
..2
...
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<string> #include<set> #include<cmath> #include<list> #include<deque> #include<cstdlib> #include<bitset> #include<stack> #include<map> #include<queue> using namespace std; typedef long long ll; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define pushup() tree[rt]=tree[rt<<1]+tree[rt<<1|1] const int INF=0x3f3f3f3f; const double PI=acos(-1.0); const double eps=1e-6; const ll mod=1e9+7; const int maxn=100005; ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} ll lcm(ll a,ll b){return a/gcd(a,b)*b;} const int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; struct node{ int x,y,id; node(int a,int b,int c):x(a),y(b),id(c){} }; struct node1{ int x,y,id,steps; node1(int a,int b,int c,int d):x(a),y(b),id(c),steps(d){} }; int n,m,sump,s[10]; vector<node> p[10]; char mp[1050][1050]; queue<node> que; queue<node1> que1; void BFS() { while(que.size()) { node tmp=que.front(); int id=tmp.id; que1.push(node1(tmp.x,tmp.y,tmp.id,0)); while(que.size()&&que.front().id==id) //判断第一个队列元素是否为当前压入队列是同一个玩家 { que1.push(node1(que.front().x,que.front().y,que.front().id,0)); que.pop(); } while(que1.size()) { node1 now=que1.front(); que1.pop(); if(now.steps==s[now.id]){ que.push(node(now.x,now.y,now.id)); //走到最后一步继续压入第一个队列 continue; } for(int i=0;i<4;i++){ int dx=now.x+dir[i][0]; int dy=now.y+dir[i][1]; if(dx>=0&&dx<n&&dy>=0&&dy<m&&mp[dx][dy]=='.'){ mp[dx][dy]='0'+now.id; que1.push(node1(dx,dy,now.id,now.steps+1)); } } } } } int main() { ios::sync_with_stdio(false); cin.tie(0); cin>>n>>m>>sump; for(int i=1;i<=sump;i++) cin>>s[i]; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ cin>>mp[i][j]; if(mp[i][j]>='0'&&mp[i][j]<='9') p[mp[i][j]-'0'].push_back(node(i,j,mp[i][j]-'0')); //同一个玩家的城堡压入同一个向量里 } } for(int i=1;i<=sump;i++) for(int j=0;j<p[i].size();j++) que.push(p[i][j]); BFS(); int ans[10]; memset(ans,0,sizeof(ans)); for(int i=0;i<n;i++) for(int j=0;j<m;j++) for(int k=1;k<=sump;k++) if(mp[i][j]==(k+'0')) ans[k]++; cout<<ans[1]; for(int i=2;i<=sump;i++) cout<<" "<<ans[i]; cout<<endl; return 0; }