如何解决这个动态编程问题(制胜策略)?

时间:2019-10-07 10:07:01

标签: arrays dynamic-programming

我遇到了这个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;    
}

我想确认我的方法是否正确,如果正确,那么我需要改变什么?我可以做得更好吗?

谢谢:-)

1 个答案:

答案 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)