求教为什么需要动归?
查看原帖
求教为什么需要动归?
126077
さくたi桜楼主2021/6/20 09:13

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;
}
2021/6/20 09:13
加载中...