刘汝佳蓝书上的题,标程做法是从终点倒着$spfa$,我是二分答案正着$spfa$判断可不可行。效果是一样的。

【注意】多组数据建边一定要清零啊QAQ!!!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std; int S, T, p; struct Node {
int v, nex;
Node ( int v = , int nex = ) :
v ( v ), nex ( nex ) { }
} Edge[]; int h[], stot;
void add ( int u, int v ) {
Edge[++stot] = Node ( v, h[u] );
h[u] = stot;
} int vis[], dis[];
queue < int > q;
bool Spfa ( int mid ) {
memset ( vis, , sizeof ( vis ) );
memset ( dis, -0x3f3f3f3f, sizeof ( dis ) );
q.push ( S ); vis[S] = ; dis[S] = mid;
while ( !q.empty ( ) ) {
int u = q.front ( ); q.pop ( ); vis[u] = ;
for ( int i = h[u]; i; i = Edge[i].nex ) {
int v = Edge[i].v;
if ( v > && dis[v] < dis[u] - ) {
dis[v] = dis[u] - ;
if ( !vis[v] ) { vis[v] = ; q.push ( v ); }
} else if ( v <= && ( dis[v] < dis[u] - ( dis[u] + ) / ) ) {
dis[v] = dis[u] - ( dis[u] + ) / ;
if ( !vis[v] ) { vis[v] = ; q.push ( v ); }
}
}
}
return dis[T] >= p;
} bool Check ( int mid ) {
return Spfa ( mid );
} int erfen ( ) {
int l = p, r = , ans;
while ( l <= r ) {
int mid = ( l + r ) >> ;
if ( Check ( mid ) ) r = mid - , ans = mid;
else l = mid + ;
}
return ans;
} int main ( ) {
freopen ( "toll.in", "r", stdin );
freopen ( "toll.out", "w", stdout );
int ti = , n;
while ( scanf ( "%d", &n ) == ) {
if ( n == - ) break;
memset ( h, , sizeof ( h ) );
for ( int i = ; i <= n; i ++ ) {
char u, v;
scanf ( "\n%c %c", &u, &v );
add ( u - 'A', v - 'A' );
add ( v - 'A', u - 'A' );
}
char s, t;
scanf ( "%d %c %c", &p, &s, &t );
S = s - 'A'; T = t - 'A';
int ans = erfen ( );
printf ( "Case %d: %d\n", ++ti, ans );
}
}

第一眼看到“最大独立集”,想的完了完了,不会啊怎么办。五分钟后,woc这不就是最长上升子序列吗,好水啊...然后心想这道题班上可能会全a吧,t3要认真才行叻。

结果原来大家都没发现吗...

可以发现每个点到原序列它后面比它小的点都连有一条双向边,要使一个集合里面任意两点都没有连边,在原序列里面这个集合就一定是一个不下降序列。要求最大,那就是最大上升子序列叻...(因为$a[i]$保证不等所以上升就好了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std; int a[], dp[]; int main ( ) {
freopen ( "sort.in", "r", stdin );
freopen ( "sort.out", "w", stdout );
int n;
scanf ( "%d", &n );
for ( int i = ; i <= n; i ++ ) scanf ( "%d", &a[i] );
memset ( dp, 0x3f3f3f3f, sizeof ( dp ) );
for ( int i = ; i <= n; i ++ ) {
int pos = lower_bound ( dp + , dp + + n, a[i] ) - dp;
dp[pos] = a[i];
}
for ( int i = n; i >= ; i -- )
if ( dp[i] < 0x3f3f3f3f ) { printf ( "%d", i ); break; }
return ;
}

数据明显是状压,可是发现一个状态要存好多东西存不下怎么办!那就多开几个数组呗...

分别储存每个状态红、绿、白钥匙有多少个,每次更新首先保证所有钥匙的和是最大的,其次保证白钥匙数量最多。

然而是很不严谨的...QAQ(但是数据水我们就不在意这些细节叻~

这样会把一些情况给筛掉,导致后面的情况不能进入。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std; int n;
int Red[(<<)+], Green[(<<)+], White[(<<)+];
int R[], G[], KR[], KG[], W[]; int main ( ) {
freopen ( "room.in", "r", stdin );
freopen ( "room.out", "w", stdout );
scanf ( "%d", &n );
for ( int i = ; i <= n; i ++ ) scanf ( "%d", &R[i] );
for ( int i = ; i <= n; i ++ ) scanf ( "%d", &G[i] );
for ( int i = ; i <= n; i ++ ) scanf ( "%d", &KR[i] );
for ( int i = ; i <= n; i ++ ) scanf ( "%d", &KG[i] );
for ( int i = ; i <= n; i ++ ) scanf ( "%d", &W[i] );
int k0, k1, k2;
scanf ( "%d%d%d", &k0, &k1, &k2 );
memset ( Red, -, sizeof ( Red ) );
memset ( Green, -, sizeof ( Green ) );
memset ( White, -, sizeof ( White ) );
Red[] = k0, Green[] = k1, White[] = k2;
for ( int i = ; i < ( << n ); i ++ ) {
for ( int j = ; j <= n; j ++ ) {
if ( ! ( ( i >> ( j - ) ) & ) ) {
int s = i | ( << ( j - ) );
int wu = max ( G[j] - Green[i], );
if ( wu > White[i] ) continue;
if ( Red[i] + ( White[i] - wu ) >= R[j] ) {
int pre = Red[i] + Green[i] + White[i] - R[j] - G[j] + KR[j] + KG[j] + W[j];
int now = Red[s] + Green[s] + White[s];
if ( now <= pre ) {
int rn = max ( , R[j] - Red[i] ), gn = max ( , G[j] - Green[i] );
int wn = rn + gn;
if ( now == pre && White[s] > White[i] - wn + W[j] ) continue;
Red[s] = max ( , Red[i] - R[j] ) + KR[j], Green[s] = max ( , Green[i] - G[j] ) + KG[j] ;
White[s] = White[i] - wn + W[j];
}
}
}
}
}
int ans = ;
for ( int i = ; i < ( << n ); i ++ )
ans = max ( ans, Red[i] + Green[i] + White[i] );
printf ( "%d", ans );
return ;
}

正解如下:

#include<cstring>
#include<cstdio>
#include<iostream>
#define fo(i,n) for(int i=0;i<n;i++)
using namespace std;
const int N=;
int dR[N],dG[N],rR[N],rG[N],rW[N],ky[N],n,f[][],z;
int main(){
freopen("room.in","r",stdin);
freopen("room.out","w",stdout);
cin>>n;
fo(i,n) cin>>dR[i];
fo(i,n) cin>>dG[i];
fo(i,n) cin>>rR[i];
fo(i,n) cin>>rG[i];
fo(i,n) cin>>rW[i];
cin>>ky[]>>ky[]>>ky[];
int sum=ky[]+ky[]+ky[];
memset(f,-,sizeof f);
f[][ky[]]=ky[];
fo(i,<<n){
int k0=ky[],k1=ky[],r=sum;
fo(j,n)
if(i>>j&){
k0+=rR[j];
r+=rR[j]+rG[j]+rW[j]-dR[j]-dG[j];
}
for(int j=;j<=k0;j++){
if(f[i][j]==-) continue;
int fr=f[i][j];
int k=r-fr-j;
fo(l,n){
if(i>>l&) continue;
int r=max(,dR[l]-j),g=max(,dG[l]-k);
int &q=f[i|(<<l)][max(,j-dR[l])+rR[l]];
if(fr>=r+g)
q=max(q,fr-r-g+rW[l]);
}
z=max(z,j+k+fr);
}
}
cout<<z<<endl;
}

离$AK$只有清零一步之遥5555555,我还是tclQAQ

抱恨离场QAQ

【9.7校内测试】【二分+spfa】【最长上升子序列】【状压DP+贪心(?)】的更多相关文章

  1. 【bzoj5161】最长上升子序列 状压dp+打表

    题目描述 现在有一个长度为n的随机排列,求它的最长上升子序列长度的期望. 为了避免精度误差,你只需要输出答案模998244353的余数. 输入 输入只包含一个正整数n.N<=28 输出 输出只包 ...

  2. BZOJ.3591.最长上升子序列(状压DP)

    BZOJ 题意:给出\(1\sim n\)的一个排列的一个最长上升子序列,求原排列可能的种类数. \(n\leq 15\). \(n\)很小,参照HDU 4352这道题,我们直接把求\(LIS\)时的 ...

  3. bzoj5161 最长上升子序列 状压DP(DP 套 DP) + 打表

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5161 题解 回顾一下以前用二分求 LIS 的方法:令 \(f[i]\) 表示长度为 \(i\) ...

  4. BZOJ 5161: 最长上升子序列 状压dp+查分

    好神啊 ~ 打表程序: #include <cstdio> #include <cstring> #include <algorithm> #define N 14 ...

  5. Luogu 3402 最长公共子序列(二分,最长递增子序列)

    Luogu 3402 最长公共子序列(二分,最长递增子序列) Description 经过长时间的摸索和练习,DJL终于学会了怎么求LCS.Johann感觉DJL孺子可教,就给他布置了一个课后作业: ...

  6. 51nod 1376 最长上升子序列的数量 | DP | vector怒刷存在感!

    51nod 1376 最长上升子序列的数量 题解 我们设lis[i]为以位置i结尾的最长上升子序列长度,dp[i]为以位置i结尾的最长上升子序列数量. 显然,dp[i]要从前面的一些位置(设为位置j) ...

  7. HDU3247 Resource Archiver (AC自动机+spfa+状压DP)

    Great! Your new software is almost finished! The only thing left to do is archiving all your n resou ...

  8. bzoj3380: [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一(spfa+状压DP)

    数据最多14个有宝藏的地方,所以可以想到用状压dp 可以先预处理出每个i到j的路径中最小权值的最大值dis[i][j] 本来想用Floyd写,无奈太弱调不出来..后来改用spfa 然后进行dp,这基本 ...

  9. 【BZOJ-1097】旅游景点atr SPFA + 状压DP

    1097: [POI2007]旅游景点atr Time Limit: 30 Sec  Memory Limit: 357 MBSubmit: 1531  Solved: 352[Submit][Sta ...

随机推荐

  1. zedboard学习记录.2.PS+PL 流水灯与uart

    1.建立一个工程. 硬件设计 2.IP integrator -> create block desgin;Run Block Automation. 3.add IP -> AXI GP ...

  2. 深入理解Spring系列之十二:@Transactional是如何工作的

    转载 https://mp.weixin.qq.com/s/ZwhkUQF1Nun9pNrFI-3a6w 首先从说起.配置了,就必定有对应的标签解析器类,查看NamespaceHandler接口的实现 ...

  3. UIAutomation Diagram

  4. itext 生成pdf文件添加页眉页脚

    原文来自:https://www.cnblogs.com/joann/p/5511905.html 我只是记录所有jar版本,由于版本冲突及不兼容很让人头疼的,一共需要5个jar, 其中itextpd ...

  5. cmder中文显示相关问题解决方案(1.3以上版本)

    cmder虽然Windows命令行的进阶版,虽然好看易用,但其中文编码一直是个问题.网上有不少博客给出解决方案,大部分都已因为版本更新失效.本文解决方案针对1.3以上版本的cmder用户 中文字体重叠 ...

  6. WEB-INF下资源访问问题

    原文链接:http://blog.csdn.net/u010921701/article/details/67637527 问题描述:建了一个Web工程,将js.css等放到了WEB-INF文件下,发 ...

  7. fullpage.js 具体使用方法

    1.fullpage.js  下载地址 https://github.com/alvarotrigo/fullPage.js 2.fullPage.js 是一个基于 jQuery 的插件,它能够很方便 ...

  8. 关于IdByName 为什么一个消息主题要有 Id和 Name的解释

  9. 通过EPROCESS获取进程名

    上一篇写自我保护时用到了,主要是不同版本的位置不同.找了一下,发现XP和win7的情况分别如下. WIN7 lkd> dt nt!_EPROCESS +0x000 Pcb : _KPROCESS ...

  10. appium---【Mac】Appium-Doctor提示WARN:“applesimutils cannot be found”解决方案

    报错提示“ applesimutils cannot be found”截图如下: 解决方案: brew tap wix/brew brew install applesimutils 再次执行app ...