dp方程错了吗

P1005 [NOIP2007 提高组] 矩阵取数游戏

纠正一下是这段 ``` #include<bits/stdc++.h> #define debug(x) cout<<"x is "<<x<<endl #define N 1000 #define k m-(r-l) int a[N];unsigned long long f[N][N]; using namespace std; int main(){ int n,m,ans=0;cin>>n>>m; while(n){ memset(f,0,sizeof(f)); memset(a,0,sizeof(a)); for(int i=1;i<=m;++i) cin>>a[i]; for(int l=1;l<=m;l++) for(int r=m;r>=l;r--){ f[l][r]=max(f[l-1][r]+a[l-1]*(unsigned long long)pow(2,k),f[l][r+1]+a[r+1]*(unsigned long long)pow(2,k) ); } //debug(f[i][l][r]); unsigned long long x=0; for(int l=1;l<=m;++l) for(int r=m;r>=l;--r) x=max(f[l][r],x); ans+=x; ///debug(n); n--; } //debug(ans); cout<<ans<<endl; return 0; } ```
by ALinus @ 2019-10-29 13:46:34


int128 吧
by nth_element @ 2019-10-29 14:05:35


要高精 QWQ
by huangzirui @ 2019-10-29 14:15:47


@[nth_element](/space/show?uid=77131) @[huangzirui](/space/show?uid=35891) 我的意思是样例过不了
by ALinus @ 2019-10-29 23:04:53



by 修己凡 @ 2019-10-30 00:11:19


啊 Venn 让我帮您调一下 1. 您的区间dp出锅了,第一维枚举长度(修改为len),第二维枚举左端点。 2. 您的转移方程出锅了,见修复代码。 3. 您没有高精。 ```cpp #include<bits/stdc++.h> #define debug(x) cout<<"x is "<<x<<endl #define N 1000 #define k m-(r-l) int a[N]; unsigned long long f[N][N]; using namespace std; int main() { int n,m,ans=0; cin>>n>>m; while(n) { memset(f,0,sizeof(f)); memset(a,0,sizeof(a)); for(int i=1;i<=m;++i) cin>>a[i]; for(int len=0;len<m;len++) for(int l=1;l+len<=m;l++) { int r=len+l; f[l][r]=max(f[l+1][r]+a[l]*pow(2,k),f[l][r-1]+a[r]*pow(2,k)); } //debug(f[i][l][r]); unsigned long long x=0; for(int l=1;l<=m;++l) for(int r=m;r>=l;--r) x=max(f[l][r],x); ans+=x; ///debug(n); n--; } //debug(ans); cout<<ans<<endl; return 0; } ``` 在此贴一个简易高精,有锅会失精,但本题数据太水,可以水过。 ```cpp struct int128{ long long high,low; }; long long p=1e18; int128 max(int128 a,int128 b) { if(a.high>b.high) return a; if(a.high<b.high) return b; if(a.low>b.low) return a; if(a.low<b.low) return b; return a; } int128 operator + (int128 a,int128 b) { int128 k; k.high=0,k.low=0; k.low=a.low+b.low; k.high=k.low/p+a.high+b.high; k.low%=p; return k; } int128 operator * (int128 a,int b) { int128 k; k.low=0,k.high=0; k.low=a.low*b; k.high+=k.low/p+b*a.high;//???? k.low%=p; return k; } ``` 以上。 @[CrazyBoyM](/space/show?uid=117252)
by 恶灬心 @ 2019-10-30 02:27:11


@[恶灬心](/space/show?uid=74598) 感谢感谢. 几点疑惑 1.我看大部分题解的方程都是以枚举l和r左右端点作为区间表示,为什么我原来也这样写就不行呢 2.这个高精度看起来比大家写的简洁多了,我准备背一下,但是比较关心这个最多能压多少位,自己用的时候注意一下 3.近些年在省级比赛中已经不考察高精度了,时间有限,有必要加强关于基本高精运算题的练习嘛 以上,恳请赐教,感谢
by ALinus @ 2019-10-30 23:04:37


@[CrazyBoyM](/space/show?uid=117252) 1. 你观察你枚举的顺序和改过的顺序。 你的r总是由大到小,但是你大的范围每次不是一个确定的值,有锅。 而从小到大枚举,每次是由确定的值走向不确定。 2. 大概64位,但高精已经不常用了。如果两个超大精度相乘,极有可能失精,最好办法还是背数组高精板子。
by 恶灬心 @ 2019-10-31 15:09:02


我看错题了,也是72,正解要一行一行转移然后求最大
by 猪小屁 @ 2019-11-04 11:15:28


|