日常................
LIS裸题............真的不需要题解吧......
设定一个数组low[i]表示长度为i的LIS的最小的结尾,我们可以发现low内的数组一定是单增的,所以我们可以在a【i】大于末项的时候更新,然后将每一个不大于末项的a[i]用lower_bound二分找到其在low中的位置然后更新
最后输出low数组的长度就好了
#include
#include
const int MAXN=1e5+5;
const int INF=0x7fffffff;
int low[MAXN];
int a[MAXN];
int n;
int ans;
int main()
{
//std::freopen("lis.in","r",stdin);
//std::freopen("lis.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
low[i]=INF;
}
low[1]=a[1];
ans=1;
for(int i=2;i<=n;i++)
{
if(a[i]>low[ans])
{
low[++ans]=a[i];
}
else
{
low[std::lower_bound(low+1,low+1+ans,a[i])-low]=a[i];
}
}
printf("%d\n",ans);
return 0;
}
T2
树形dp,然而我用状压的假算法苟到了40分............
我们定义dp[u][i]为在u为根的子树当中,选取i个点构成联通块需要的最小割边数量
转移方程简单的要死........自己都不知道考试的时候为什么想不到
dp[u][i]=std::min(dp[u][i]+1,min(dp[u][i-j]+dp[v][j]))
全部枚举直接dp就完成了
#include
#include
#include
const int MAXN=150+5;
const int INF=1e9+7;
class Edge
{
public:
int nxt;
int to;
}edge[MAXN<<1];
int head[MAXN];
int num;
void add(int from,int to)
{
edge[++num].nxt=head[from];
edge[num].to=to;
head[from]=num;
}
int n,k;
int siz[MAXN];
int dp[MAXN][MAXN];
int ans=INF;
void dfs(int u,int f)
{
std::memset(dp[u],63,sizeof(dp[u]) );
siz[u]=1;
dp[u][1]=0;
for(int i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v==f)
{
continue;
}
dfs(v,u);
siz[u]+=siz[v];
for(int i=k;i>=1;i--)
{
int tmp=dp[u][i]+1;
for(int j=1;j
T3
轮廓线裸题,全班AC率最高的题目.......
定义dp[i][s]为状态为s,取到第i行的方案数,然后按照正常的轮廓线更新就好了
具体轮廓线的套路比较复杂,在这里就不讲了
详情可以参见这篇博客
https://blog.csdn.net/cyendra/article/details/38171319
代码实现非常简单
#include
#include
#include
#include
#define LL long long
const int MAXN=15;
LL dp[2][1<r)
std::swap(r,c);
memset(dp,0,sizeof(dp));
now=0;
dp[now][(1<
T4
背包裸题
设dp[k][t]表示现在选取了价值总和为k的集合中是否能包含t
而新添加的元素一定对k产生影响,一定会加上a[i]
而对于t可能影响可能不影响
所以直接转移就好
dp[j+a[i]][t]|=dp[j][t];
dp[j+a[i]][t+a[i]]|=dp[j][t];
#include
#include
const int MAXN=505;
bool dp[MAXN][MAXN];
int a[MAXN];
int main()
{
//std::freopen("coin.in","r",stdin);
//std::freopen("coin.out","w",stdout);
int n,k;
std::scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
std::scanf("%d",a+i);
}
dp[0][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=k-a[i];j>=0;j--)
{
for(int t=j;t>=0;t--)
{
if(dp[j][t])
{
dp[j+a[i]][t]|=dp[j][t];
dp[j+a[i]][t+a[i]]|=dp[j][t];
}
}
}
}
int cnt=0;
for(int i=0;i<=k;i++)
{
if(dp[k][i])
{
cnt++;
}
}
std::printf("%d\n",cnt);
for(int i=0;i<=k;i++)
{
if(dp[k][i])
{
std::printf("%d ",i);
}
}
std::printf("\n");
return 0;
}