https://www.nowcoder.com/acm/contest/140#question
A
题意:
白云可以走[L,R]米,每秒只有两种走法,走1米或者k米。求有几种走法。
思路:简单dp,很像以前那个入门dp,走台阶的问题,求出dp[i][j]:走到i位置前一步走了1米(j==0)前一步走了k米(j==1).的种类数,很简单,注意long long就行
代码:
#include
#define mod 1000000007
using namespace std;
long long n,k,L,R,dp[100005][2],sum[100005];
int main()
{
scanf("%lld%lld",&n,&k);
for(int i=1;i
D
题意:n个店铺,每个店铺买入卖出的价格给出,成本无限多,每次白云手里最多拿一件东西,求最大利润下的最小交易数量
思路:这也是一道水题,画画图分析一下,是个贪心,就是所有递增序列左端点买入,右端点卖出。找连续递增子序列就可以,最后注意一下最后一个数的处理就行了
代码:
#include
#define inf 800000000
#define ll long long
#define mod 1000000007
using namespace std;
ll a[100010];
int main()
{
int T;
cin>>T;
while(T--)
{
int i,n;
bool f=0;
ll now=0,cnt=0;
cin>>n;
for(i=0;i>a[i];
}
a[n]=0;
for(i=0;ia[i+1]&&f)
{
now+=a[i];
cnt++;
f=false;
}
}
cout<
I
题意:[n,n]的矩阵,从边缘往另一个方向有行驶的车。车的速度相同,给m个坏点,求最多安排几辆车,车互相之间不能撞车,并且不能走过坏点。
思路:对于无坏点的各个矩阵算最大车辆数,找规律得,n是偶数,最多安排2*n辆,n为奇数,最多安排2(n-1)辆。就是每行每列都会安排上一辆车,然后奇数的时候,中间的一行一列只能安排一辆车,然后对于坏点记录其影响的行列,最后判断一共影响了几行几列。。奇数时,中间的行列要特殊考虑
(PS:下面是队友的代码,跟自己的思路有出入,但差别不大,就不敲了)
代码:
#include
#define inf 800000000
#define ll long long
#define mod 1000000007
using namespace std;
bool delx[100005],dely[100005];
int main()
{
int cnt=0;
int n,m;
bool f=0;
cin>>n>>m;
if(n%2)
{
while(m--)
{
int x,y;
cin>>x>>y;
if(x==y&&x==(n+1)/2&&!f)
{
cnt++;
f=1;
}
else
{
if(!delx[x]&&x!=(n+1)/2)
{
cnt++;
delx[x]=1;
}
if(!dely[y]&&y!=(n+1)/2)
{
cnt++;
dely[y]=1;
}
if(!delx[x]&&x==(n+1)/2)
{
delx[x]=1;
}
if(!dely[y]&&y==(n+1)/2)
{
dely[y]=1;
}
}
}
if(delx[(n+1)/2]&&dely[(n+1)/2]&&!f)
{
cnt++;
}
}
else
{
while(m--)
{
int x,y;
cin>>x>>y;
if(!delx[x])
{
cnt++;
delx[x]=1;
}
if(!dely[y])
{
cnt++;
dely[y]=1;
}
}
}
int res;
if(n%2)
{
res=2*(n-1)+1-cnt;
}
else
{
res=2*n-cnt;
}
cout<
G
题意:数轴上n个集装箱,第i个集装箱位于坐标x[i],有a[i]件货物
现在把集装箱进行一些移动,求所有货物移动总距离不超过T/2的情况下做多能把多少个集装箱移到同一个位置?
思路:看了题解,然后摸了很久的标称终于弄懂了,标称没有注释,,真的好难理解。。反正这就是个二分,感觉还有dp的思想,check()种用到了i跟i-1的关系,所以只需要找1集装箱的具体位置就可以,后面的都可以从i-1转移到i,详细见代码,,注释的十分清楚了。。
代码
#include
#define gs(c) (c < '0' || c > '9')
#define gc(c) c = getchar()
#define getint() ({ int w = 0; char gc(c); while (gs(c)) gc(c); while (!gs(c)) w = w*10+c-'0', gc(c); w; })
#define d(i, j) (int64)(x[j] - x[i])
using namespace std;
const int N = 500050;
typedef long long int64;
int n, x[N], a[N];
int64 T, s[N];
int64 sum(int l, int lc, int r, int rc) //集装箱l的第lc个物品到集装箱r的第rc-1个物品一共有多少物品
{
return l == r? rc - lc: s[r - 1] - s[l] + a[l] - lc + rc;
}
bool check(int64 need) {
int l = 1, lc = 1, r = n + 1, rc = 1;
//从集装箱l的lc个物品开始转移,need个物品,到及集装箱r的rc-1,位置,rc位置已将是第need+1个物品了,不移。
int64 cur = 0, sa = 0;//从第一个集装箱第一个物品开始移都移到第一个集装箱(l=1;lc=1)查找{r,rc},并计算这时最多移的个数
for (int i = 1; i <= n; ++i) {
if (sa + a[i] <= need) sa += a[i], cur += d(1, i) * a[i];
else { r = i, rc = need - sa + 1, cur += d(1, i) * (rc - 1); break; }
}
if (cur <= T) return 1;
for (int i = 2; i <= n; ++i)
{
cur += d(i - 1, i) * (sum(l, lc, i, 1) - sum(i, 1, r, rc));//从1点的第一个物品开始的need个物品移到集装箱i的花费,集装箱i左面的从i-1移到i,集装箱i及右面的要原路返回到i。
while (r <= n && d(l, i) > d(i, r))//能往右移
{
int z = min(a[l] - lc + 1, a[r] - rc + 1);//集装箱l选的移到r的剩余空间,最多移的个数
cur += (d(i, r) - d(l, i)) * z;//移完后的花费
if (lc += z, lc > a[l]) ++l, lc = 1;//l选的小,则l集装箱一个都没选,转到下一个集装箱
if (rc += z, rc > a[r]) ++r, rc = 1;//r剩余的空间小,r集装箱选满,转到下一个集装箱
}
if (cur <= T) return 1;
}
return 0;
}
int main() {
cin>>n>>T;
assert(1<=n&&n<=500000);
assert(1<=T&&T<=1e18);
T /= 2;
for (int i = 1; i <= n; ++i) x[i] = getint(),assert(1<=n&&n<=n),assert(i==1||x[i]>x[i-1]);
for (int i = 1; i <= n; ++i) a[i] = getint(),assert(0<=a[i]&&a[i]<=1e4), s[i] = s[i - 1] + a[i];
int64 ll = 0, rr = s[n];//二分答案,做多能转移的货物
while (ll < rr) {
int64 mm = (ll + rr + 1) >> 1;
if (check(mm)) ll = mm;
else rr = mm - 1;
}
cout<