我遇到了这个dp问题。它如下:-
艾莉亚·史塔克(Arya Stark)和桑莎·史塔克(Sansa Stark)是姐妹,但常常出于一种或另一种原因而相互争斗。最近,Sansa在狩猎游戏中作弊,击败了Arya,并取笑了她。艾莉亚很生气,想报仇。艾莉亚(Arya)叫姐姐珊莎(Sansa)参战,珊莎(Sansa)接受了。
战斗由R轮组成,每轮将测试不同的技能。该技能可能是射箭,剑斗或其他任何技能。每轮比赛结束后,比赛的获胜者将获得一个积分。在完成所有R轮之后,得分最高的那一轮将被视为总冠军。
艾莉亚很生气,不仅希望赢得这场战斗,而且还希望击败桑莎,这样一轮回合后,她的积分至少是桑莎积分的P倍。她正在忙着准备战斗,并听说了您的技能。她希望您找到在所提供的条件下击败Sansa并报仇的方法。
获胜顺序区分了不同的方式。 示例:让我们考虑一下,有3个回合。
案例1:Arya赢得第一轮,Sansa赢得第二轮,Arya赢得第三轮
订单:-艾莉亚,珊莎,艾莉亚
案例2:Arya赢得了第一轮,Arya也赢得了第二轮,Sansa赢得了第三轮
订单:-Arya,Arya,Sansa
以上两种情况互不相同,被认为是两种不同的方式。
注意:由于答案可能很大,所以取10 ^ 9 + 7为模。
输入格式: 输入的第一行包含测试用例数T 每个测试用例的唯一一行由两个以空格分隔的整数R和P组成。
约束: 1 <= T <= 10
1 <= R <= 1000
1 <= P <= R
输出格式:-
对于每个测试用例,请在单独的行中打印出可能的方法。
TestCase 1示例
输入
2 4 2 2 2
输出
3
1
说明 测试案例1:
在给定条件下,艾莉亚可以通过三种方式获胜
方法1:前三回合由Arya赢得,最后一回合由Sansa赢得
Arya, 艾莉亚 艾莉亚 珊莎
方法2:艾莉亚(Arya)赢得了前两轮比赛。 Sansa赢得了第三回合,Arya赢得了最后一回合。
Arya, 艾莉亚 珊莎 艾莉亚
方法3:艾莉亚(Arya)赢得了所有四回合。
Arya, 艾莉亚 艾莉亚 艾莉亚
测试案例2:在这种情况下,只有一种获胜方式,即如果艾莉亚(Arya)在两轮比赛中都获胜。
Arya, 艾莉亚
我的问题代码:-
enter code gghere
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
ll e=1000000007;
ll a2[2000][2000];
int main()
{ll t;
cin>>t;
ll t1=t;
while(t--)
{
ll r,p;
cin>>r>>p;
//map<pair<ll,ll>,ll> a2;
//a2[{1,0}]=1;
a2[1][0]=1;
ll w[20000][9];
ll op=0;
w[op][0]=1;
w[op][1]=0;
w[op][2]=1;
op++;
ll i1=0;
ll i=2;
while(i<=r)
{
ll b[20000][7];
ll pass=0;
i1=0;
while(i1<op)
{
ll c1,c2;
ll c3;
c1=w[i1][0]%e;
c2=w[i1][1]%e;
c3=w[i1][2]%e;
if((c1+1)>=p*c2)
{
//....(c1+1,c2)+=c3
b[pass][0]=c1+1;
b[pass][1]=c2;
b[pass][2]=c3%e;
pass++;
}
if(c1>=p*(c2+1))
{
b[pass][0]=c1;
b[pass][1]=c2+1;
b[pass][2]=c3%e;
//.......(c1,c2+1)+=c3
pass++;
}
i1++;
}
i1=0;
while(i1<op)
{
ll x1=w[i1][0];
ll x2=w[i1][1];
a2[x1][x2]=0;
w[i1][0]=0;
w[i1][1]=0;
w[i1][2]=0%e;
i1++;
}
op=0;
ll j=0;
while(j<pass)
{
ll x1=b[j][0];
ll x2=b[j][1];
ll x3=b[j][2]%e;
if(a2[x1][x2]==0)
{
w[op][0]=x1;
w[op][1]=x2;
op++;
}
else
{
}
a2[x1][x2]=(a2[x1][x2]%e+x3%e)%e;
j++;
}
i1=0;
while(i1<op)
{
ll m1=w[i1][0];
ll m2=w[i1][1];
w[i1][2]=a2[m1][m2]%e;
i1++;
}
i++;
}
i1=0;
ll c4=0;
while(i1<op)
{
ll c1,c2;
ll c3;
c1=w[i1][0]%e;
c2=w[i1][1]%e;
//cout<<c1<<" "<<c2;
//cout<<"\n";
c3=w[i1][2]%e;
c4=(c4%e+c3%e)%e;
//cout<<c1<<" "<<c2<<" "<<c3<<"\n";
c4=c4%e;
i1++;
}
cout<<c4;
cout<<"\n";
ll o=0;
while(o<=1500)
{
ll p=0;
while(p<=1200)
{
a2[o][p]=0;
p++;
}
o++;
}
}
return 0;
}
我想确认我的方法是否正确,如果正确,那么我需要改变什么?我可以做得更好吗?
谢谢:-)
答案 0 :(得分:0)
不了解您的方法。您可以将此问题转换为以下等式:
f(currentMatch,aryaWon) = f(currentMatch+1,aryaWon+1) + f(currentMatch+1,aryaWon)
从您可以得出的状态开始,
sansaWon = currentMatch - aryaWon
基本情况将是
if(aryaWon < p * sansaWon ) return 0
和
if(currentMatch == r) return 1
这是实现:
#define mxn 1003
#define mod 1000000007
int p,r;
int dp[mxn][mxn];
int f(int match,int arya) {
int sansa = match - arya;
if(arya < p * sansa) return 0;
if(match == r) return 1;
if(dp[match][arya] != -1)
return dp[match][arya];
int ans = f(match+1,arya + 1) + f(match+1,arya);
ans %= mod;
return dp[match][arya] = ans;
}
int main()
{
int t;
cin >> t;
while(t--) {
cin >> r >> p;
memset(dp,-1,sizeof dp);
cout << f(0,0) << endl;
}
return 0;
}
时间和空间复杂度为O(r^2)