@hhzhhzhhz
2019-06-01T16:55:01.000000Z
字数 3439
阅读 363
解题报告
模拟
1. 连着的1点一次向后一格
2. 1中间的1个0也点击一次
3. 连着两个零及以上选择跳出循环,转入下一个1,过程中需要两次点击
4. 用临时变量,存储还有多少未读
#include<bits/stdc++.h>using namespace std;int main() {int n,a[1010],j=0;cin>>n;for(int i=1; i<=n; i++) {cin>>a[i];if(a[i]==1)j++;}a[n+1]=-1;int ans=0;for(int i=1; i<=n; i++) {if(a[i]==1) {int t=0;while((a[i] || a[i+1]) && j) {if(a[i]==1) j--;a[i]=0,t++,i++;}ans+=t;if(j) ans+=1 ;}}cout<<ans;return 0;}

- 预处理:
也可写作dfs:
预处理后,第n家店的杨梅汁的单价是最低的,所以dfs从最后一家店开始搜索。
考虑两种情况
- 一次性买完 p 份
- 不一次性买完 p-1 份
#include<bits/stdc++.h>#define LL long longLL ans=1e18,v[33],p[33],l,n;using namespace std;void dfs(int n,int l, LL m ) {if(l==0 || n==0) return ;LL tmp=((l-1)/v[n]+1)*p[n]+m;ans=min(ans,tmp);dfs(n-1,l%v[n],m+l/v[n]*p[n]);}int main() {cin>>n>>l;for(int i=1; i<=n; i++) {cin>>p[i];//价格v[i]=pow(2,i-1);//体积}for(int i=2; i<=n; i++) {p[i]=min(2*p[i-1],p[i]);}dfs(n,l,0);// 第几家店 ; 还要多少 ; 花了多少cout<<ans;return 0;}

搜索;
传三个参数 a: 还能放多少体积; b:已经放到多高; c:放了多少体积
每一层选择放木块或不放木块;
1. 放木块将 a-木块体积; b+1; c+木块体积
2. 不放木块 a-> 当前木块体积-1(避免下层继续选择同体积木块); b不变;c不变
#include<bits/stdc++.h>#define ll long long#define lowbit(x) (x)&-(x)#define N 10010#define P 10007#define D double#define ull unsigned llusing namespace std;int n;struct nod {int t,v;} ans[100010];int cnt;bool cmp(nod a, nod b) {if(a.t!=b.t) return a.t>b.t;else return a.v>b.v;}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 f*x;}void dfs(int need,int nv,int nh) {int x;for(x=1; x*x*x<=need; x++);//枚举边长if(need<=7) {ans[cnt].t=nh+need;ans[cnt].v=nv+need;cnt++;return ;}dfs(need-pow(x-1,3),nv+pow(x-1,3),nh+1);dfs(pow(x-1,3)-1,nv,nh);}int main() {n=read();dfs(n,0,0);sort(ans,ans+cnt,cmp);cout<<ans[0].t<<" "<<ans[0].v<<endl;return 0;}

规律+二分
- 代码
#include<bits/stdc++.h>#define ll long long#define lowbit(x) (x)&-(x)#define N 10010#define P 10007#define D double#define ull unsigned llusing 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 f*x;}ll m,n,k;ll find(LL x) { // 计算比x小的数的个数dfll sum=0;for(int i=1; i<=n; i++) {sum += (m <= x/i)?m:(x/i); // min(m,x/i) 是每一行中比x小的数的个数(若i*m<=x,则会有m个数满足要求,否则会有x/i个数满足),也可以用if,else的写法 或 ? : 表达式的写法.}return sum;}ll ef(ll l, ll r, ll k) {ll mid;while(l <= r) {mid=(l+r)/2;if(find(mid) < k) l=mid+1; // 要找的数在后面,区间下限继续增大else r=mid-1; // 要找的数在前面,区间上限继续减小}return l;}int main() {cin>>m>>n>>k;cout<ef(1,n*m,k);cout<<endl;return 0;