附上大神链接:http://www.cnblogs.com/alihenaixiao/p/4836471.html#3276283 自己写的A,C,借鉴的大神的B,D;
这个我的头文件习惯了写将近40行,所以就写这了,下面就不写了啊;
#include<iostream>
#include<sstream>
#include<iomanip>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#include<list>
#include<stack>
#include<map>
#include<set>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
using namespace std;
#define rep(a,b,c) for(int a=b;a<=c;a++)
#define drep(a,b,c) for(int a=b;a>=c;a--)
#define mkp make_pair
#define pub push_back
#define pob pop_back
typedef long long ll;
typedef long double lb;
typedef pair<int,int> pii;
const int maxn = 100000+10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const int dx[8]={0,0,1,-1,1,1,-1,-1};
const int dy[8]={1,-1,0,0,1,-1,1,-1};
580A:
题目大意:
求一个非下降子串,然后就是细节处理,我觉得我这么写还是挺好的,挺清楚的,以后都这么写了;
基本思路:
就算不比较,让自己也是一个,所以最短也是1吧,然后这样的话很自然想到从idex=2开始比较,然后就特别对待一下idex=n的情况,不然可能都跳出循环了,还没有把值赋给res;
代码如下:
int arr[maxn];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&arr[i]);
int maxx=1;
int cnt=1;
for(int i=2;i<=n;i++)
{
if(arr[i]>=arr[i-1]) cnt++;
else
{
if(cnt>maxx) maxx=cnt;
cnt=1;
}
if(i==n)
{
if(cnt>maxx) maxx=cnt;
}
}
printf("%d\n",maxx);
}
580B:
题目大意:
一群人去参加庆祝趴,每个人都有两个属性(身价,贡献),在庆祝趴里面身价最大的和身价最小的差值不能大于等于d,问庆祝趴内所有人的总贡献最大为多少?
基本思路:
首先你选那么一堆人,这一堆人里面最大和最小身价的差值肯定是小于等于d,然后这很自然让人想到先排个序吧,然后就是尺取法了吧;
代码如下:
struct Node
{
ll m,s;
bool operator<(const Node& a)const
{
return m<a.m;
}
}node[maxn];
int main()
{
ios::sync_with_stdio(false);
int n,d;
cin>>n>>d;
node[0].m=node[0].s=0;
rep(i,1,n) cin>>node[i].m>>node[i].s;
sort(node+1,node+n+1);
rep(i,1,n) node[i].s+=node[i-1].s;
ll mx=node[1].s;
int left=1;
rep(i,2,n)
{
while(node[i].m-node[left].m>=d&&left<i)
left++;
mx=max(mx,node[i].s-node[left-1].s);
}
cout<<mx<<endl;
}
580C:
题目大意:
有一个树,1节点是home,叶子节点是公园,在节点中可能会有猫,问从home出发在路上不能经过连续的m个猫,问能到达几个不同的公园?
基本思路:
树上的dfs就好了,然后注意弄一下叶子结点,然后就没啥了,偶,对了,用了一下邻接表,这玩意太好使了,而且比用vector快很多,(其实后自己是能做出来的,有想法的,但总是不敢去做,这很不应该,一起不是就喜欢做难题来着吗?将这种品质拾起来);
代码如下:
int n,m,res,pos;
int arr[maxn],du[maxn];
struct Node
{
int to,next;
}node[maxn*2];
int head[maxn];
void AddEdge(int u,int v)
{
node[pos].to=v;
node[pos].next=head[u];
head[u]=pos++;
}
void dfs(int s,int f,int cnt)
{
for(int i=head[s];i!=-1;i=node[i].next)
{
int t=node[i].to;
if(t!=f)
{
if(arr[t])
{
if(cnt+1>m) continue;
else dfs(t,s,cnt+1);
}
else dfs(t,s,0);
}
}
if(du[s]==1&&s!=1) res++;
}
int main()
{
ios::sync_with_stdio(false);
memset(head,-1,sizeof(head));
memset(du,0,sizeof(du));
pos=res=0;
cin>>n>>m;
rep(i,1,n) cin>>arr[i];
int u,v;
rep(i,1,n-1)
{
cin>>u>>v;
du[u]++;
du[v]++;
AddEdge(u,v);
AddEdge(v,u);
}
if(arr[1]) dfs(1,0,1);
else dfs(1,0,0);
cout<<res<<endl;
}
580D:
题目大意:
以后碰到类似的选哪些的题目,应该自然就会想到状态压缩dp了,然后这个dp的状态要怎么定义呢,因为加分像必须是吃完第一个接着吃第二个才能加分,所以这样的话设置一个二维的,然后第一维就是状态,第二维就是最后吃的那一道菜是哪一道,然后就能写出这个程序了(即使这样我也想不出来啊,不过做完这个题之后我觉得以后遇到类似的我一定能想出来,主要就是&一下看idex=j这道菜是不是在里面,就是是不是吃过,然后k这里这个|,就是加进去)
代码如下:
const int maxx=270000+10;
int dp[maxx][20],arr[20],up[20][20];
int check(int x)
{
int cnt=0;
while(x)
{
if(x%2) cnt++;
x>>=1;
}
return cnt;
}
int main()
{
ios::sync_with_stdio(false);
int n,m,d;
cin>>n>>m>>d;
rep(i,0,n-1)
{
cin>>arr[i];
dp[1<<i][i]=arr[i];
}
int u,v,w;
rep(i,0,d-1)
{
cin>>u>>v>>w;
u--,v--;
up[u][v]=w;
}
int res=-1;
rep(i,1,(1<<n))
{
rep(j,0,n-1)
{
if(i&(1<<j))
{
rep(k,0,n-1)
{
if(i&(1<<k)) continue;
dp[i|(1<<k)][k]=max(dp[i|(1<<k)][k],dp[i][j]+arr[k]+up[j][k]);
}
}
if(check(i)==m)
res=max(res,dp[i][j]);
}
}
cout<<res<<endl;
}