大佬求助

P1464 Function

CE_TAP @ 2023-11-17 19:53:25

代码爆RE了,不知道为什么

#include<iostream>
using namespace std;
#define int long long
int f[55][55][55];
int w(int a,int b,int c){
    if(f[a][b][c]) return f[a][b][c];
    if(a<=0 || b<=0 || c<=0) return 1;
    if(a< b && b<c) return f[a][b][c]= w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
    return f[a][b][c]=  w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1);
}
signed main(){
    int a=0,b=0,c=0;
    while(cin>>a>>b>>c){
        if(a==-1 && b==-1 && c==-1){ return 0;}
        printf("w(%lld, %lld, %lld) = ",a,b,c);
        if(a>20 || b>20 ||c>20) a=b=c=20;
        printf("%lld\n",w(a,b,c));
        a=b=c=0;
    }
    return 0;
}

by rnf5114 @ 2023-11-17 20:03:01

@CE_TAP f数组开大点


by OldVagrant @ 2023-11-17 20:14:54

@CE_TAP 您的w函数里,第二个if应该放在第一个if之前。因为如果a,b,c三个数中有任何一个小于0,都会导致你访问到了f数组的负数下标。


by dontwannacry @ 2023-11-17 20:18:35

@CE_TAP

1.你的代码中:

if(f[a][b][c]) return f[a][b][c];
if(a<=0 || b<=0 || c<=0) return 1

但是值为负的数组下标会造成越界,导致了re 此处应将两行调换位置

2.这样改完后只有60分(WA on 5,7):注意题面中

但是你现在main()中先判了第二条再去w()中判第一条,所以WA了

AC code:

#include<iostream>
using namespace std;
#define int long long
int f[55][55][55];
int w(int a,int b,int c){
    if(a<=0 || b<=0 || c<=0) return 1;
    if(a>20 || b>20 ||c>20) a=b=c=20;
    if(f[a][b][c]) return f[a][b][c];
    //if(a<=0 || b<=0 || c<=0) return 1;
    if(a< b && b<c) return f[a][b][c]= w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
    return f[a][b][c]=  w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1);
}
signed main(){
    int a=0,b=0,c=0;
    while(cin>>a>>b>>c){
        if(a==-1 && b==-1 && c==-1){ return 0;}
        printf("w(%lld, %lld, %lld) = ",a,b,c);
        //if(a>20 || b>20 ||c>20) a=b=c=20;
        printf("%lld\n",w(a,b,c));
        a=b=c=0;
    }
    return 0;
}

by CE_TAP @ 2023-11-17 20:24:33

@dontwannacry @OldVagrant @rnfmabj5114 感谢各位大佬


|