lyk最近计划按顺序做n道题目,每道题目都分为很多分数档次,lyk觉得这些题太简单了,于是它想到了一个好玩的游戏。
lyk决定将每道题目做出其中的某个分数,使得这n道题目的逆序对个数最多。
为了方便,假设共有m个分数档次,并且会给m个分数档次分配一个题目编号,表示该题目会出现这个分数档次。
题目保证每道题都存在至少一个分数档次。(例如样例中5道题目的分数分别是5,6,3,4,7,共有4个逆序对)
Input
第一行两个数n,m(n<=20,m<=100)。
接下来m行,每行一个数ai,表示第ai道题目可能会有i这个分数的档次。
Output
一个数表示最多逆序对个数。
Input示例
5 7
1
2
3
4
1
2
5
Output示例
4
题解
问题可以对应为在m个分值中选择n个,组成最大逆序对,然后就是裸题了。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<set>
#include<ctime>
#include<vector>
#include<cmath>
#include<algorithm>
#include<map>
#define mod 1000000007
#define ll long long
#define inf 1e9
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,m,dp[1<<20];
int main()
{
n=read();m=read();
int all=1<<n;
for (int j=1;j<all;j++) dp[j]=-inf;
for (int i=1;i<=m;i++)
{
int x=read();x--;
for (int j=0;j<all;j++)
{
if (dp[j]==-inf) continue;
if (j&(1<<x)) continue;
int sum=0;
for (int k=x+1;k<n;k++)
if (j&(1<<k)) sum++;
dp[j|(1<<x)]=max(dp[j]+sum,dp[j|(1<<x)]);
}
}
printf("%d",dp[all-1]);
return 0;
}