文章标题
来源:互联网 发布:淘宝床上用品床罩 编辑:程序博客网 时间:2024/06/09 16:53
Spot
描述
有n个泥点,排成一排,第i个泥点坐标为ai。有m个木板,第i个木板长为li。现在用尽可能少的木板覆盖所有泥点。
问:使用木板的最少数量以及最优方案数(mod 1000000007),若不能完全覆盖,请输出“NO”。
注意:
泥点可重复覆盖,木板可重叠。
计算方案时,长度相等的两个板不等价,视为两种板。
输入
第1行:一个数n
第2行:n个数a1,a2…an(从小到大给出)
第3行:一个数m
第4行:m个数l1,l2…ln
输出
第1行,一个数,使用木板的最少数量
第2行,一个数,最优方案数
若不能完全覆盖,请输出“NO”
样例输入
1
0
1
10
样例输出
1
10
数据范围和约定
对于20%的数据:n=1
对于另外20%的数据:m=1
对于100%的数据:
1<=n,m<=15
0<=ai<=1000000000
1<=li<=1000000000
时空限定
内存限制为 512 MB
时间限制为 1 s
评测环境和细则
评测开启-O2优化
评测软件为lemon
评测忽略行尾空格
文件名
提交文件名为spot.cpp/pas
输入文件名为spot.in
输出文件名为spot.out
n,m<=15,先确定是状压
一开始f[i][j],i表示前i个木板,j压的是泥点
再用g[i][j] 在dp的时候记录方案数
但是要考虑的情况会多到爆炸
在卡了一个下午后,本蒟蒻毅然决然的决定 换!状!态!!!!
用f[i][j],i表示前i个泥点,j压的是木板,f[i][j]表示方案数
初始化成负数
最后再扫一遍f[n][0-maxp],找不是负数中最小的,没找着就输出”NO”
这样比以前的好处是:
泥点最后一定要全都选完,但木板不一定,比较好转移。
错误的第一次code
#include<cstdio>#include<cstring>#include<iostream>#define mem(a,b) memset(a,b,sizeof(a))#define ll long longusing namespace std;const int mod=1000000007;const int N=1<<15;ll minn(ll a,ll b){return a<b?a:b;}ll maxn(ll a,ll b){return a>b?a:b;}int n,m,maxp;int pos[21],len[21];int f[16][N+10];ll g[16][N+10];ll num;ll ans;void out11(){ printf("\n\n"); for(int i=1;i<=m;++i) { for(int j=0;j<=maxp;++j) printf("%d ",f[i][j]); printf("\n"); } printf("\n"); for(int i=0;i<=m;++i) { for(int j=0;j<=maxp;++j) printf("%lld ",g[i][j]); printf("\n"); } printf("\n");}int main(){ //freopen("1.txt","r",stdin); freopen("spot6.in","r",stdin); //freopen("spot5.in","r",stdin); //freopen("spot.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&pos[i]); scanf("%d",&m); for(int i=1;i<=m;++i) scanf("%d",&len[i]); // n为泥点个数 m为木板个数 maxp=(1<<n)-1; mem(f,0x7f); f[0][0]=0; g[0][0]=1; int r,temp,l1,r1,l2,r2,judge1; ll llnum,lrnum,rrnum,rlnum,fangan; ll temp1,temp2; int qian,now; for(int i=1;i<=m;++i) for(int j=0;j<=maxp;++j) { if(f[i][j]==f[i-1][j]){g[i][j]=(g[i-1][j]+g[i][j])%mod;} else if(f[i][j]>f[i-1][j]){f[i][j]=f[i-1][j];g[i][j]=g[i-1][j];} qian=maxp+1; for(int l=1;l<=n;++l) { r=l;temp=j; while(pos[r]-pos[l]+1<=len[i]&&r<=n)++r;--r; now=0; for(int p=l;p<=r;++p) if(temp&(1<<(p-1))) now|=(1<<(p-1)); if(now==qian)continue; qian=now; judge1=0; for(int p=l;p<=r;++p) { l2=p; if(temp&(1<<(p-1))) { judge1=1; break; } } for(int p=r;p>=l;--p) { r2=p; if(temp&(1<<(p-1))) break; } if(!judge1)continue;//选的区间中 状态都没有 l1=l2-1; while(l1>=1&& !((1<<(l1-1))&temp) )--l1; r1=r2+1; while(r1<=n&& !((1<<(r1-1))&temp) )++r1; llnum=(l1==0?-0x7fffffff:pos[l1]+1); lrnum=pos[r2]-len[i]+1; rlnum=pos[l2]+len[i]-1; rrnum=(r1==n+1?0x7fffffff:pos[r1]-1); temp1=minn(rlnum,rrnum)-pos[r2]+1; temp2=pos[l2]-maxn(llnum,lrnum)+1; //printf("temp1=%lld temp2=%lld\n",temp1,temp2); fangan=(minn(temp1,temp2))%mod; //if(fangan<0) // cout<<fangan<<endl; //printf("i=%d j=%d l=%d r=%d lnum=%lld rmun=%lld fangan=%lld\n",i,j,l,r,lnum,rnum,fangan); for(int p=l;p<=r;++p) temp=temp&(~(1<<(p-1))); if(f[i][j]==f[i-1][temp]+1) g[i][j]=(g[i][j]+g[i-1][temp]*fangan%mod)%mod; else if(f[i][j]>f[i-1][temp]+1) { f[i][j]=f[i-1][temp]+1; g[i][j]=g[i-1][temp]*fangan%mod; } } } if(f[m][maxp]==f[0][maxp]) { printf("NO"); //while(1); return 0; } printf("%d\n",f[m][maxp]); for(int i=1;i<=m;++i) if(f[i][maxp]==f[m][maxp]) ans=(ans+g[i][maxp])%mod; printf("%lld",ans); //可以用dfs??? //dfs(int x,int now) //外面一个judge数组或二进制变量记录泥点选没选 //x:第几块木板 //now:以前用的木板数 //可能左右挪比较恶心吧!!! /*judge=0; dfs(1,0,1);*/ //out11(); while(1); return 0;}正确的大神第一次想的那样的标程:AC我的code:
- 文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题 文章标题 文章标题 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- css字体设置相关属性
- 异步提交表单,页面跳转问题
- jquery中$(this)代表的含义
- CSS字体属性
- 机器学习——EM算法 知识点与面试总结
- 文章标题
- Java 8系列之Stream的强大工具Collector
- luceneday-02
- 【Mongo】集群测试(容灾+查询+并发)
- 解析C语言结构体,位段
- MVP模式Demo
- 常用的页面跳转函数
- 学习springmvc的第十三天(自定义类型转换器ConversionServiceFactoryBean)
- 树莓派交叉编译环境搭建 for Mac