RT
推了一个最优规则,不知道问题在哪里
规则:每行头尾比大小,先取小的,然后把取了的消掉,产生新的头尾(如果大小相同,那就比他们往里面靠一个的大小,如头就是往后一个,尾就是往前一个,还相同就再往里靠,以此类推,最后比到同一个位置或者相邻位置数相等就直接算前面的小)
然而这样算出来和答案不一样,手算也不一样,求教规则哪有问题
别说用动归,这只是个尝试,加深对题目的理解
#include <iostream>
#include <cstdio>
#include <cmath>
typedef __int128 ull;
typedef unsigned short int usi;
using namespace std;
ull sum=0;
usi n,m,jz[81][81],head[81],end[81];
void scan(__int128 &x)
{
x=0;
int f=1;
char ch;
if((ch=getchar())=='-')f=-f;
else x=x*10+ch-'0';
while((ch=getchar())>='0'&& ch <='9')
x=x*10+ch-'0';
x*=f;
}
void print(__int128 x)
{
if(x<0)
{
x=-x;
putchar('-');
}
if(x>9)print(x/10);
putchar(x%10+'0');
}
bool mycompare(usi y,usi h,usi e)
{
if(h==e)return true;
if(jz[y][h]==jz[y][e]){
if(h+1==e)return true;
else return mycompare(y,h+1,e-1);
}
else{
if(jz[y][h]<jz[y][e])return true;
else return false;
}
}
void develop_sum(usi _n,usi x)
{
if(mycompare(x,head[x],end[x])){
sum+=(jz[x][head[x]]*(ull)pow(2,_n));
head[x]++;
}
else{
sum+=(jz[x][end[x]]*(ull)pow(2,_n));
end[x]--;
}
return;
}
int main()
{
cin>>n>>m;
for(usi i=0;i<n;i++){
head[i]=0;
end[i]=m-1;
for(usi j=0;j<m;j++)cin>>jz[i][j];
}
for(usi i=1;i<m;i++)for(usi j=0;j<n;j++)develop_sum(i,j);
for(usi j=0;j<n;j++)sum+=(jz[j][head[j]]*(ull)pow(2,m));
print(sum);
cout<<endl;
return 0;
}